📄 chapter10.html
字号:
<font color=#0000ff>public</font> <font color=#0000ff>boolean</font> accept(File dir, String name) {
<font color=#009900>// Strip path information:</font>
String f = <font color=#0000ff>new</font> File(name).getName();
<font color=#0000ff>return</font> f.indexOf(afn) != -1;
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>DirFilter</B> class
“implements” the <B>interface</B> <B>FilenameFilter</B>. (Interfaces
were covered in Chapter 7.) It’s useful to see how simple the
<B>FilenameFilter</B> <B>interface</B> is:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#0000ff>public</font> <font color=#0000ff>interface</font> FilenameFilter {
<font color=#0000ff>boolean</font> accept(File dir, String name);
}</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It says that all that this type of
object does is provide a method called <B>accept( )</B>. The whole reason
behind the creation of this class is to provide the <B>accept( )</B> method
to the <B>list( )</B> method so that <B>list( )</B> can <I>call
back</I> <B>accept( )</B> to determine which file names should be included
in the list. Thus, this technique is often referred to as a
<A NAME="Index1064"></A><I>callback</I> or sometimes a
<A NAME="Index1065"></A><I>functor</I> (that is, <B>DirFilter</B> is a functor
because its only job is to hold a method). Because <B>list( )</B> takes a
<B>FilenameFilter</B> object as its argument, it means that you can pass an
object of any class that implements <B>FilenameFilter</B> to choose (even at
run-time) how the <B>list( )</B> method will behave. The purpose of a
callback is to provide flexibility in the behavior of code.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><B>DirFilter</B> shows that just
because an <B>interface</B> contains only a set of methods, you’re not
restricted to writing only those methods. (You must at least provide definitions
for all the methods in an interface, however.) In this case, the
<B>DirFilter</B> constructor is also created.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>accept( )</B> method
must accept a <B>File</B> object representing the directory that a particular
file is found in, and a <B>String</B> containing the name of that file. You
might choose to use or ignore either of these arguments, but you will probably
at least use the file name. Remember that the <B>list( )</B> method is
calling <B>accept( )</B> for each of the file names in the directory object
to see which one should be included – this is indicated by the
<B>boolean</B> result returned by <B>accept( )</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To make sure that what you’re
working with is only the name and contains no path information, all you have to
do is take the <B>String</B> object and create a <B>File</B> object out of it,
then call <B>getName( )</B> which strips away all the path information (in
a platform-independent way). Then <B>accept( )</B> uses the
<A NAME="Index1066"></A><A NAME="Index1067"></A><B>String </B>class
<B>indexOf( )</B> method to see if the search string <B>afn</B> appears
anywhere in the name of the file. If <B>afn</B> is found within the string, the
return value is the starting index of <B>afn</B>, but if it’s not found
the return value is -1. Keep in mind that this is a simple string search and
does not have regular expression “wildcard” matching such as
“fo?.b?r*” which is much more difficult to
implement.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>list( )</B> method
returns an array. You can query this array for its length and then move through
it selecting the array elements. This ability to easily pass an array in and out
of a method is a tremendous improvement over the behavior of C and
C++.</FONT><BR></P></DIV>
<A NAME="Heading312"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Anonymous inner classes</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This example is ideal for rewriting
using an
<A NAME="Index1068"></A><A NAME="Index1069"></A><A NAME="Index1070"></A>anonymous
inner class (described in Chapter 7). As a first cut, a method <B>filter( )
</B>is created that returns a handle to a
<B>FilenameFilter</B>:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: DirList2.java</font>
<font color=#009900>// Uses Java 1.1 anonymous inner classes</font>
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> DirList2 {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> FilenameFilter
filter(<font color=#0000ff>final</font> String afn) {
<font color=#009900>// Creation of anonymous inner class:</font>
<font color=#0000ff>return</font> <font color=#0000ff>new</font> FilenameFilter() {
String fn = afn;
<font color=#0000ff>public</font> <font color=#0000ff>boolean</font> accept(File dir, String n) {
<font color=#009900>// Strip path information:</font>
String f = <font color=#0000ff>new</font> File(n).getName();
<font color=#0000ff>return</font> f.indexOf(fn) != -1;
}
}; <font color=#009900>// End of anonymous inner class</font>
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
<font color=#0000ff>try</font> {
File path = <font color=#0000ff>new</font> File(<font color=#004488>"."</font>);
String[] list;
<font color=#0000ff>if</font>(args.length == 0)
list = path.list();
<font color=#0000ff>else</font>
list = path.list(filter(args[0]));
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < list.length; i++)
System.out.println(list[i]);
} <font color=#0000ff>catch</font>(Exception e) {
e.printStackTrace();
}
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Note that the argument to
<B>filter( )</B> must be
<A NAME="Index1071"></A><A NAME="Index1072"></A><B>final</B>. This is required
by the anonymous inner class so that it can use an object from outside its
scope.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This design is an improvement
because the <B>FilenameFilter</B> class is now tightly bound to <B>DirList2</B>.
However, you can take this approach one step further and define the anonymous
inner class as an argument to <B>list( )</B>, in which case it’s even
smaller:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: DirList3.java</font>
<font color=#009900>// Building the anonymous inner class "in-place"</font>
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> DirList3 {
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(<font color=#0000ff>final</font> String[] args) {
<font color=#0000ff>try</font> {
File path = <font color=#0000ff>new</font> File(<font color=#004488>"."</font>);
String[] list;
<font color=#0000ff>if</font>(args.length == 0)
list = path.list();
<font color=#0000ff>else</font>
list = path.list(
<font color=#0000ff>new</font> FilenameFilter() {
<font color=#0000ff>public</font> <font color=#0000ff>boolean</font>
accept(File dir, String n) {
String f = <font color=#0000ff>new</font> File(n).getName();
<font color=#0000ff>return</font> f.indexOf(args[0]) != -1;
}
});
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < list.length; i++)
System.out.println(list[i]);
} <font color=#0000ff>catch</font>(Exception e) {
e.printStackTrace();
}
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The argument to <B>main( )</B>
is now <B>final</B>, since the anonymous inner class uses <B>args[0]</B>
directly.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This shows you how anonymous inner
classes allow the creation of quick-and-dirty classes to solve problems. Since
everything in Java revolves around classes, this can be a useful coding
technique. One benefit is that it keeps the code that solves a particular
problem isolated together in one spot. On the other hand, it is not always as
easy to read, so you must use it judiciously.</FONT><BR></P></DIV>
<A NAME="Heading313"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
A sorted directory listing</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Ah, you say that you want the file
names <I>sorted</I>? Since there’s no support for sorting in Java 1.0 or
Java 1.1<A NAME="Index1073"></A> (although sorting <I>is</I> included in Java
1.2<A NAME="Index1074"></A>), it will have to be added into the program directly
using the <B>SortVector </B>created in Chapter 8:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: SortedDirList.java</font>
<font color=#009900>// Displays sorted directory listing</font>
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>import</font> c08.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> SortedDirList {
<font color=#0000ff>private</font> File path;
<font color=#0000ff>private</font> String[] list;
<font color=#0000ff>public</font> SortedDirList(<font color=#0000ff>final</font> String afn) {
path = <font color=#0000ff>new</font> File(<font color=#004488>"."</font>);
<font color=#0000ff>if</font>(afn == <font color=#0000ff>null</font>)
list = path.list();
<font color=#0000ff>else</font>
list = path.list(
<font color=#0000ff>new</font> FilenameFilter() {
<font color=#0000ff>public</font> <font color=#0000ff>boolean</font>
accept(File dir, String n) {
String f = <font color=#0000ff>new</font> File(n).getName();
<font color=#0000ff>return</font> f.indexOf(afn) != -1;
}
});
sort();
}
<font color=#0000ff>void</font> print() {
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < list.length; i++)
System.out.println(list[i]);
}
<font color=#0000ff>private</font> <font color=#0000ff>void</font> sort() {
StrSortVector sv = <font color=#0000ff>new</font> StrSortVector();
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < list.length; i++)
sv.addElement(list[i]);
<font color=#009900>// The first time an element is pulled from</font>
<font color=#009900>// the StrSortVector the list is sorted:</font>
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < list.length; i++)
list[i] = sv.elementAt(i);
}
<font color=#009900>// Test it:</font>
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
SortedDirList sd;
<font color=#0000ff>if</font>(args.length == 0)
sd = <font color=#0000ff>new</font> SortedDirList(<font color=#0000ff>null</font>);
<font color=#0000ff>else</font>
sd = <font color=#0000ff>new</font> SortedDirList(args[0]);
sd.print();
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A few other improvements have been
made. Instead of creating <B>path</B> and <B>list</B> as local variables to
<B>main( )</B>, they are members of the class so their values can be
accessible for the lifetime of the object. In fact, <B>main( )</B> is now
just a way to test the class. You can see that the constructor of the class
automatically sorts the list once that list has been created.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The sort is case-insensitive so you
don’t end up with a list of all the words starting with capital letters,
followed by the rest of the words starting with all the lowercase letters.
However, you’ll notice that within a group of file names that begin with
the same letter the capitalized words are listed first, which is still not quite
the desired behavior for the sort. This problem will be fixed in Java
1.2<A NAME="Index1075"></A>.</FONT><A NAME="_Toc375545392"></A><A NAME="_Toc408018619"></A><BR></P></DIV>
<A NAME="Heading314"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Checking for and creating directories</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>File</B> class is more than
just a representation for an existing directory path, file, or group of files.
You can also use a <B>File</B> object to create a new
<A NAME="Index1076"></A><A NAME="Index1077"></A>directory or an entire directory
path if it doesn’t exist. You can also look at the
<A NAME="Index1078"></A><A NAME="Index1079"></A>characteristics of files (size,
last modification date, read/write), see whether a <B>File</B> object represents
a file or a directory, and delete a file. This program shows the remaining
methods available with the <B>File</B> class:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: MakeDirectories.java</font>
<font color=#009900>// Demonstrates the use of the File class to</font>
<font color=#009900>// create directories and manipulate files.</font>
<font color=#0000ff>import</font> java.io.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> MakeDirectories {
<font color=#0000ff>private</font> <font color=#0000ff>final</font> <font color=#0000ff>static</font> String usage =
<font color=#004488>"Usage:MakeDirectories path1 ...\n"</font> +
<font color=#004488>"Creates each path\n"</font> +
<font color=#004488>"Usage:MakeDirectories -d path1 ...\n"</font> +
<font color=#004488>"Deletes each path\n"</font> +
<font color=#004488>"Usage:MakeDirectories -r path1 path2\n"</font> +
<font color=#004488>"Renames from path1 to path2\n"</font>;
<font color=#0000ff>private</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> usage() {
System.err.println(usage);
System.exit(1);
}
<font color=#0000ff>private</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> fileData(File f) {
System.out.println(
<font color=#004488>"Absolute path: "</font> + f.getAbsolutePath() +
<font color=#004488>"\n Can read: "</font> + f.canRead() +
<font color=#004488>"\n Can write: "</font> + f.canWrite() +
<font color=#004488>"\n getName: "</font> + f.getName() +
<font color=#004488>"\n getParent: "</font> + f.getParent() +
<font color=#004488>"\n getPath: "</font> + f.getPath() +
<font color=#004488>"\n length: "</font> + f.length() +
<font color=#004488>"\n lastModified: "</font> + f.lastModified());
<font color=#0000ff>if</font>(f.isFile())
System.out.println(<font color=#004488>"it's a file"</font>);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -