FilenameFilter接口详解

FilenameFilter:文件名过滤器。这名字起的,没说的,通俗易懂。就是在文件集合中过滤出我想要的文件。

怎么用呢?

我们看一下这个接口怎么写的。

public interface FilenameFilter {
        boolean accept(File dir, String name);
    }

好家伙!就定义了一个抽象方法,逗我呢?
不要着急!稍后你会看到这个接口和抽象方法的作用。提示:这里会显示出策略模式的强大之处。
我都是以下面这个文件来举例。
这里写图片描述

现在,我想要在D:\eclipse下找到以 .exe 结尾的文件,看下面我写的代码

public class FilenameFilterDemo {

    public static void main(String[] args) {
        File file = new File("D:\\eclipse");
        //创建一个过滤器实例
        FilenameFilterDemo filenameFilterDemo = new FilenameFilterDemo();
        FileFilter fileFilter = filenameFilterDemo.new FileFilter();
        String[] list = file.list(fileFilter);
        for (String string : list) {
            System.out.println(string);
        }
    }

    //这是一个内部类过滤器
    class FileFilter implements FilenameFilter{
        @Override
        public boolean accept(File dir, String name) {
            //String的 endsWith(String str)方法  筛选出以str结尾的字符串
            if(name.endsWith(".exe"))
                return true;
            return false;
        }
    }
}

结果:
这里写图片描述
这里我重写了accept()方法,让它能过滤出以 .exe 的文件。

那么这是怎么做到的呢?我们来看list(FilenameFilter filter)的源代码
 public String[] list(FilenameFilter filter) {
        //将当前File文件夹下的文件名遍历出来
        String names[] = list();
        /**
         * 如果文件夹为空,返回一个空的字符串数组,
         * 注意:如果当前文件不是目录,list()方法会返回Null
         */
        if ((names == null) || (filter == null)) {
            return names;
        }
        List<String> v = new ArrayList<>();
        //从names中取出单个文件的文件名
        for (int i = 0 ; i < names.length ; i++) {
            /**
             * 看到了吗,这里使用了accept(File dir, String name);方法
             * 如果过滤到了.exe文件,返回true
             * 封装到list集合中
             */
            if (filter.accept(this, names[i])) {
                v.add(names[i]);
            }
        }
        //将list集合变成数组返回给方法调用者。
        return v.toArray(new String[v.size()]);
    }
步骤:
首先,会将File目录下的文件集封装到一个数组中。
调用accept()方法,从数组中过滤出符合条件的文件
将符合条件的文件名封装到ArrayList()集合中。
将ArrayList()转换为数组返回给调用者。

那么为什么用到了策略设计模式了呢?
不着急解释。

我再写一个文件过滤器,我想过滤出File表示的目录下 必须是文件 且 文件名长度大于10的文件(怎么这么像绕口令呢?)。
class FileFilter2 implements FilenameFilter{

        @Override
        public boolean accept(File dir, String name) {
            // TODO Auto-generated method stub
            if(!dir.isDirectory()){
                return false;
            }
            //我利用dir和name新创建了File对象,不然isFile()和length()不能用
            File subfile = new File(dir, name);
            if(subfile.isFile()){
                if(subfile.length()>10){
                    return true;
                }
            }
            return false;
        }

    }

结果:
这里写图片描述

解析

这里,我定义了两个过滤器 分别是FileFilter 和 FileFilter2。他们都实现了FilenameFileter接口。并重写了accept()方法。注意:list(FilenameFilter filefilter);
参数一直没变,总是filefilter,你会看到,方法内部一直使用的是接口的accept()方法。但将实现类传递进去,内部实际调用的是什么?是实现类FileFilter和FileFilter2的accept()方法。明白了吗?FilenameFilter将list(FilenameFilter filefilter)给欺骗了,list(FilenameFilter filefilter)一直以为方法没变,它仍然是调用接口的accept()方法,但是实际功能已经改变了,只是它不知道而已。没错这就是策略模式的强大之处,欺骗,也可以说是隐藏。 欺骗方法的实际调用者,在实际运行时给他调包。隐藏实现细节,方法调用者不必知道方法是如何实现的,它是谁创建的,以及它具体的功能是什么(我只知道它是用来过滤文件的,过滤什么类型的文件,我也不知道)调用者只需要调用这个方法就行,不必来回改变。灵活度极高。注意:这里使用了接口的解耦合思想,java的多态特性。
在说说另外一个优点:延伸性。
如果需求变了,我想过滤出其他条件的文件。那么,我只需要实现FilenameFileter创建相应的子类,将这个子类传给list(FilenameFilter filefilter);还能查询出你要的文件。是不是延伸性极好?

总结:

想学设计模式的同学,我推荐大家一本书 Head First设计模式,一看就懂,比之这样语诉,图片更能深入人心,理解的也更快。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值