按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
…………………………………………………………Page 290……………………………………………………………
for(int i = 0; i 《 list。length; i++)
System。out。println(list'i');
} catch(Exception e) {
e。printStackTrace();
}
}
}
class DirFilter implements FilenameFilter {
String afn;
DirFilter(String afn) { this。afn = afn; }
public boolean accept(File dir; String name) {
// Strip path information:
String f = new File(name)。getName();
return f。indexOf(afn) != …1;
}
} ///:~
DirFilter 类“实现”了 interface FilenameFilter (关于接口的问题,已在第7 章进行了详述)。下面让
我们看看FilenameFilter 接口有多么简单:
public interface FilenameFilter {
boolean accept(文件目录; 字串名);
}
它指出这种类型的所有对象都提供了一个名为 accept()的方法。之所以要创建这样的一个类,背后的全部原
因就是把accept()方法提供给 list()方法,使 list()能够“回调”accept() ,从而判断应将哪些文件名包
括到列表中。因此,通常将这种技术称为“回调”,有时也称为“算子”(也就是说,DirFilter 是一个算
子,因为它唯一的作用就是容纳一个方法)。由于 list()采用一个 FilenameFilter 对象作为自己的自变量
使用,所以我们能传递实现了 FilenameFilter 的任何类的一个对象,用它决定(甚至在运行期)list()方法
的行为方式。回调的目的是在代码的行为上提供更大的灵活性。
通过DirFilter,我们看出尽管一个“接口”只包含了一系列方法,但并不局限于只能写那些方法(但是,
至少必须提供一个接口内所有方法的定义。在这种情况下,DirFilter 构建器也会创建)。
accept()方法必须接纳一个 File 对象,用它指示用于寻找一个特定文件的目录;并接纳一个String,其中
包含了要寻找之文件的名字。可决定使用或忽略这两个参数之一,但有时至少要使用文件名。记住 list()方
法准备为目录对象中的每个文件名调用accept(),核实哪个应包含在内——具体由 accept()返回的“布尔”
结果决定。
为确定我们操作的只是文件名,其中没有包含路径信息,必须采用String 对象,并在它的外部创建一个
File 对象。然后调用 getName(),它的作用是去除所有路径信息(采用与平台无关的方式)。随后,accept()
用String 类的 indexOf()方法检查文件名内部是否存在搜索字串〃afn〃。若在字串内找到 afn,那么返回值就
是afn 的起点索引;但假如没有找到,返回值就是…1。注意这只是一个简单的字串搜索例子,未使用常见的
表达式“通配符”方案,比如〃fo?。b?r*〃;这种方案更难实现。
list()方法返回的是一个数组。可查询这个数组的长度,然后在其中遍历,选定数组元素。与 C 和C++的类
似行为相比,这种于方法内外方便游历数组的行为无疑是一个显著的进步。
1。 匿名内部类
下例用一个匿名内部类(已在第7 章讲述)来重写显得非常理想。首先创建了一个filter()方法,它返回指
向FilenameFilter 的一个句柄:
//: DirList2。java
// Uses Java 1。1 anonymous inner classes
import java。io。*;
289
…………………………………………………………Page 291……………………………………………………………
public class DirList2 {
public static FilenameFilter
filter(final String afn) {
// Creation of anonymous inner class:
return new FilenameFilter() {
String fn = afn;
public boolean accept(File dir; String n) {
// Strip path information:
String f = new File(n)。getName();
return f。indexOf(fn) != …1;
}
}; // End of anonymous inner class
}
public static void main(String'' args) {
try {
File path = new File(〃。〃);
String'' list;
if(args。length == 0)
list = path。list();
else
list = path。list(filter(args'0'));
for(int i = 0; i 《 list。length; i++)
System。out。println(list'i');
} catch(Exception e) {
e。printStackTrace();
}
}
} ///:~
注意 filter()的自变量必须是final。这一点是匿名内部类要求的,使其能使用来自本身作用域以外的一个
对象。
之所以认为这样做更好,是由于FilenameFilter 类现在同DirList2 紧密地结合在一起。然而,我们可采取
进一步的操作,将匿名内部类定义成 list()的一个参数,使其显得更加精简。如下所示:
//: DirList3。java
// Building the anonymous inner class 〃in…place〃
import java。io。*;
public class DirList3 {
public static void main(final String'' args) {
try {
File path = new File(〃。〃);
String'' list;
if(args。length == 0)
list = path。list();
else
list = path。list(
new FilenameFilter() {
public boolean
accept(File dir; String n) {
String f = new File(n)。getName();
290
…………………………………………………………Page 292……………………………………………………………
return f。indexOf(args'0') != …1;
}
});
for(int i = 0; i 《 list。length; i++)
System。out。println(list'i');
} catch(Exception e) {
e。printStackTrace();
}
}
} ///:~
main()现在的自变量是 final,因为匿名内部类直接使用args'0'。
这展示了如何利用匿名内部类快速创建精简的类,以便解决一些复杂的问题。由于Java 中的所有东西都与类
有关,所以它无疑是一种相当有用的编码技术。它的一个好处是将特定的问题隔离在一个地方统一解决。但
在另一方面,这样生成的代码不是十分容易阅读,所以使用时必须慎重。
2。 顺序目录列表
经常都需要文件名以排好序的方式提供。由于 Java 1。0 和Java 1。1 都没有提供对排序的支持(从 Java 1。2
开始提供),所以必须用第8 章创建的 SortVector将这一能力直接加入自己的程序。就象下面这样:
//: SortedDirList。java
// Displays sorted directory listing
import java。io。*;
import c08。*;
public class SortedDirList {
private File path;
private String'' list;
public SortedDirList(final String afn) {
path = new File(〃。〃);
if(afn == null)
list = path。list();
else
list = path。list(
new FilenameFilter() {
public boolean
accept(File dir; String n) {
String f = new File(n)。getName()