1. 简介
在 Java 引入 @FunctionalInterface
注解之前,就已经存在不少函数式接口(Functional Interface)。FilenameFilter
就是其中之一。
虽然它属于较早的一批接口,但在某些场景下依然实用。本文将带你快速了解它的作用和使用方式,并探讨它在现代 Java 开发中的定位。
2. FilenameFilter 接口详解
FilenameFilter
是一个典型的函数式接口 —— ✅ 只包含一个抽象方法,因此可以被用作 Lambda 表达式的目标类型。
其核心方法定义如下:
boolean accept(File dir, String name);
这个方法接收两个参数:
dir
:当前遍历的目录(File
对象)name
:该目录下的文件或子目录名称(不包含路径)
返回 true
表示保留该文件名,false
则过滤掉。
⚠️ 注意:它只关心“名字”,不直接操作文件内容或属性。
3. 使用方式
FilenameFilter
主要用于筛选指定目录中满足条件的文件名。java.io.File
类提供了两个重载方法支持传入 FilenameFilter
:
String[] list(FilenameFilter filter)
File[] listFiles(FilenameFilter filter)
这两个方法会返回符合过滤规则的文件名数组或 File
对象数组。
示例:筛选 JSON 文件
下面这个测试用例展示了如何使用 FilenameFilter
找出目录下所有以 .json
结尾的文件:
@Test
public void whenFilteringFilesEndingWithJson_thenEqualExpectedFiles() {
FilenameFilter filter = (dir, name) -> name.endsWith(".json");
String[] expectedFiles = { "people.json", "students.json" };
File directory = new File(getClass().getClassLoader()
.getResource("testFolder")
.getFile());
String[] actualFiles = directory.list(filter);
Assert.assertArrayEquals(expectedFiles, actualFiles);
}
✅ 要点总结:
- 使用 Lambda 简化实现,代码更简洁
endsWith(".json")
是简单粗暴但有效的匹配方式- 测试资源路径通过
ClassLoader
获取,避免硬编码路径问题(踩坑提醒:Windows 和 Linux 路径分隔符差异)
3.1 FilenameFilter 与 BiPredicate 的关系
Java 8 新增了超过 40 个通用函数式接口,其中 BiPredicate<T, U>
特别值得关注:
boolean test(T t, U u);
对比 FilenameFilter
的 accept(File dir, String name)
方法,你会发现:
✅ FilenameFilter
本质上就是 BiPredicate<File, String>
的特化版本!
也就是说:
FilenameFilter filter = (dir, name) -> name.endsWith(".json");
等价于:
BiPredicate<File, String> predicate = (dir, name) -> name.endsWith(".json");
但区别在于:
- ❌
BiPredicate
不能直接用于File.list()
方法(类型不匹配) - ✅
FilenameFilter
是专门为文件系统设计的,语义更清晰
所以虽然 BiPredicate
更通用,但在处理文件名过滤时,FilenameFilter
依然是最贴合场景的选择。
4. 总结
尽管现代 Java 提供了更强大的 Predicate
和 BiPredicate
等泛型函数式接口,但 FilenameFilter
依然有它的存在价值:
- ✅ 历史悠久,广泛存在于现有项目和 JDK API 中
- ✅ 专为文件名过滤设计,语义明确,开箱即用
- ✅ 结合 Lambda 使用,代码简洁直观
📌 因此,在合适的场景下(比如简单的目录扫描 + 文件扩展名过滤),完全可以直接使用 FilenameFilter
,不必强行“现代化”。
所有示例代码均可在 GitHub 上获取:https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-io-apis