java 中引入 File 类的目的就是为了将一个外部文件系统中的存储数据的文件和 Java 语言中的 File 类做关联,做映射。用这个 File 类去抽象代表文件系统中的文件,这才使得程序有能力通过这个 File 类去操作文件,而且在 java 中文件目录也会被当做一个 File 类去处理。计算机科学中最重要的思想就是抽象思想了吧!
File 类常用方法
和文件名相关
-
public String getName()
//取得文件或者目录的名字 -
public String getPath()
//取得文件或者目录的当前路径 -
public String getAbsolutePath()
//取得文件或者目录的在文件系统中的绝对路径
文件检测
-
public public boolean exists()
//判断文件或目录是否存在 -
public boolean canWrite()
//判断文件是否可写 -
public boolean canRead()
//判断文件是否可读 -
public boolean isFile()
//判断File对象是否代表文件 -
public boolean isDirectory()
//判断File对象是否代表目录 -
public boolean isAbsolute()
//判断File对象代表文件或目录是否是绝对路径名表示
通过文件检测中的public boolean isFile()
和public boolean isDirectory()
两个方法也证明了,Java 语言中是把文件和目录都用 File 类去抽象表示的。而且这两个方法的存在同时也证明了,在使用指定的路径构造 File 对象的时候,即便给的是个莫名其妙的路径,文件系统中根本不存在的路径,同样是可以构造对象,毕竟其构造方法中仅仅接收一个 String 类型的参数。理解这一点非常重要,因为在实际编程中用到 File 类的时候,很可能会因为路径不对,没有构造出正确的 File 对象,而导致程序出现问题。
这里也有一个做笔记的启示,根据后续的理解,回头找到原先的笔记,进行扩展和补充。如果不回头来做记录,那么好不容易得出的感悟,过段时间,一定会遗忘,也就无法将新的感悟,变成自己的基本功了。只有不断累积自己的基本功,水平才能提升。
File 类的两个重载方法
public String[] list()
和public String[] list(FilenameFilter filter)
,这两个重载方法的功能就是列举出该目录下的所有文件名(Java 中目录也被当做是一个文件处理),用一个 String[] 类型的数据封装起来作为方法返回值返回。
第二个方法public String[] list(FilenameFilter filter)
不同于第一个方法的地方在于,可以对目录下的文件进行过滤。具体实现方式是接收一个 FilenameFilter 接口类型的参数,进行过滤。
FilenameFilter 接口源码如下,可见这是 java.io 中专门设计来对文件名进行过滤的一个接口,它有一个唯一的抽象方法boolean accept(File dir,String name)
,通过这个方法来实现文件过滤的功能。其中第一个参数 dir 接收的是调用 list(FilenameFilter filter) 方法的对象 this 指针(也就是需要进行文件名过滤的的文件的父目录),第二个参数 name 是需要进行过滤的文件名。这两者组合起来才是完整的文件路径啊,所以需要调用 File 类的public File(String parent,String child)
构造函数对生成的 File 类对象进行初始化。
package java.io;
public interface FilenameFilter {
boolean accept(File dir, String name);
}
那么public String[] list(FilenameFilter filter)
方法是如何实现的呢?源码如下,可见此方法内部是先调用了 list() 方法得到该目录下的所有文件名组成的字符串数组对象,然后通过 filter 接口变量调用它的 accept() 方法进行判断是否符合过滤规则。如果符合就添加到 ArrayList 容器中,直至所有的文件名都判断完后,就转成一个字符串数组对象返回。
public String[] list(FilenameFilter filter) {
String names[] = list();
if ((names == null) || (filter == null)) {
return names;
}
List<String> v = new ArrayList<>();
for (int i = 0 ; i < names.length ; i++) {
if (filter.accept(this, names[i])) {
v.add(names[i]);
}
}
return v.toArray(new String[v.size()]);
}
那么如何使用这两个重载方法?
对于public String[] list()
方法,直接用一个目录 File 对象调用它即可。
对于public String[] list(FilenameFilter filter)
对象,首先要新建一个类实现 FilenameFilter 接口,重写 accept() 方法,指定过滤规则。然后将这个对象的引用作为参数传递给 list() 方法。这个过程就叫做回调模式!
什么叫做回调函数?
上面提到的public String[] list(FilenameFilter filter)
方法就是回调方法。到底什么叫做回调呢?比如这里 File 类提供的这个方法接受一个 FilenameFilter 接口类型的参数,该方法内部会调用该接口的 accept() 方法。但使用这个方法的前提是自定义一个类实现该接口,实现它的抽象方法。并将给类的对象作为参数传递给 list() 方法的过程就叫做回调。
抽象点的说法就是:程序员A定义了一个方法,该方法接受一个指定接口类型的参数对象,并会在该方法内部调用该接口的某个抽象方法。然后程序员B 则定义了一个类实现该接口,并重写该抽象方法,然后将对象作为参数传递给程序员A定义的方法,由程序员A的方法来回调程序员B重写的方法,这就叫做回调。
网友评论