匿名内部类用于就地实现接口或抽象类,省去单独定义类的步骤,适用于单次使用的简单回调;需实现所有抽象方法,可访问外部final或effectively final变量;lambda仅适用于函数式接口。

Java 中用匿名内部类写事件监听器或回调接口,核心是省掉单独定义类的步骤,直接在需要的地方“就地”实现接口,代码更紧凑、逻辑更集中。
适用于单次使用的简单回调
当某个监听器只在一处使用、逻辑不复杂时,匿名内部类最自然。比如 Swing 中给按钮添加点击响应:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("按钮被点了");
}
});
这里没有类名、不用声明新类文件,也不用额外实例化——new 接口名 + 大括号,直接实现抽象方法即可。
注意必须实现接口所有抽象方法
匿名内部类本质是接口(或抽象类)的子类实例,所以要满足接口契约:
- 如果接口只有一个抽象方法(如 Runnable、ActionListener),只需实现那一个;
- 若接口有多个抽象方法(如 MouseListener),就得全部实现,哪怕只关心其中一两个——这时可考虑适配器类(如 MouseAdapter)或 Java 8+ 的 Lambda 表达式;
- 不能带构造参数,但可以访问所在方法的 final 或“事实 final”局部变量(Java 8 起放宽为 effectively final)。
访问外部变量有约束
匿名内部类能引用外部方法里的变量,但这些变量必须是 final 或编译器认定不可再赋值:
String msg = "Hello";
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(msg); // ✅ 合法:msg 是 effectively final
}
});
// msg = "World"; // ❌ 如果放开这行,上面的匿名类会编译失败
和 Lambda 表达式的取舍
Java 8 引入 Lambda 后,对函数式接口(仅一个抽象方法)可用更简写法:
button.addActionListener(e -> System.out.println("按钮被点了"));
但匿名内部类仍有不可替代场景:
- 接口含多个抽象方法,又不想写完整类;
- 需要在内部类中定义字段、方法或初始化块;
- 需显式调用 super() 或 this()(虽少见);
- 项目仍在使用 Java 7 或更早版本。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











