匿名内部类是无名的接口实现类或抽象类子类,用于一次性轻量级场景;语法为new接口/抽象类(){},须实现全部抽象方法,可访问外围类成员及事实final局部变量,编译生成独立class文件。

Java 匿名内部类通过 new 接口名() {} 或 new 抽象类名() {} 的语法直接创建实例,同时实现接口方法或重写抽象方法,无需显式定义类名。
实现接口的匿名内部类
当接口只有一个抽象方法(如函数式接口)时,匿名类常用于简化回调或事件处理。编译器会自动将大括号内的代码绑定为该接口的实现。
- 语法格式:
new 接口名() { /* 实现所有抽象方法 */ }; - 必须实现接口中所有抽象方法,不能只实现部分
- 可访问所在作用域的 final 或“事实 final”局部变量(JDK 8+ 放宽了限制)
例如:
Runnable r = new Runnable() {public void run() {
System.out.println("线程执行中");
}
};
继承抽象类的匿名内部类
匿名类也可继承抽象类,但必须提供所有未实现的抽象方法的具体逻辑,构造过程会调用父类的某个构造器(默认调用无参构造;若父类无无参构造,则需在 new 后加参数)。
立即学习“Java免费学习笔记(深入)”;
- 语法格式:
new 抽象类名(构造参数) { /* 重写抽象方法 + 可选其他代码 */ }; - 可以定义实例初始化块、成员变量(不推荐)、甚至重载方法,但不能有构造器
- 如果抽象类有带参构造,new 时必须传入对应参数
例如:
AbstractListpublic String get(int index) { return "item" + index; }
public int size() { return 5; }
};
注意事项与常见误区
匿名内部类本质仍是类,有独立字节码(如 Outer$1.class),但它不可被复用,也不适合复杂逻辑。
- 不能有显式构造器,但可通过实例初始化块模拟初始化逻辑
- 不能定义静态成员(除静态 final 常量外)
- 无法直接访问外部类的非 final 局部变量(编译阶段会捕获副本)
- 使用 Lambda 表达式替代单方法接口的匿名类更简洁(如
() -> System.out.println("ok"))
什么时候该用匿名内部类
适合一次性、轻量级的实现场景,比如 GUI 事件监听、线程启动、简单 Comparator/Runnable/Callable 等。
- 逻辑简单,只用一次,不需复用
- 需要访问当前方法的局部变量(且变量是 final 或事实 final)
- 目标类型是接口或抽象类,且你不想单独写一个命名类
- 尚未迁移到 Lambda(如需 this 引用、多语句、或非函数式接口)


















