匿名内部类与Lambda表达式知识点总结

匿名内部类

基本概念

  • 匿名内部类是没有名字的内部类
  • 用于快速创建某个类或接口的子类/实现类的实例
  • 适合只使用一次的类实现

语法结构

java

1
2
3
4
new 父类构造器(参数列表) | 实现接口() {
// 匿名内部类的类体部分
方法重写/实现
};

特点

  1. 必须继承一个父类或实现一个接口
  2. 只能创建一个实例
  3. 没有构造方法(但可以有实例初始化块)
  4. 可以访问外部类的成员,包括私有成员
  5. 如果访问局部变量,该变量必须是final或事实上final的

使用场景

  • 事件监听器
  • 线程实现
  • 需要快速实现某个接口或抽象类

Lambda表达式

基本概念

  • Java 8引入的函数式编程特性
  • 用于简化函数式接口的实现
  • 本质是一个匿名函数

语法结构

java

1
2
3
(parameters) -> expression

(parameters) -> { statements; }

特点

  1. 只能用于函数式接口(只有一个抽象方法的接口)
  2. 类型可以自动推断
  3. 可以访问外部final或事实上final的局部变量
  4. 简洁明了,减少样板代码

常见函数式接口

  • Runnable -> () -> {...}
  • Consumer<T> -> (T t) -> {...}
  • Supplier<T> -> () -> {...}
  • Function<T,R> -> (T t) -> {... return R;}
  • Predicate<T> -> (T t) -> {... return boolean;}

匿名内部类 vs Lambda表达式

特性 匿名内部类 Lambda表达式
语法复杂度 较复杂 简洁
使用场景 任何类/接口 仅函数式接口
this关键字 指向匿名内部类本身 指向外部类
编译后 生成单独的.class文件 不生成.class文件,使用invokedynamic
访问外部变量 必须final或事实上final 必须final或事实上final
多重方法 可以 不可以

示例代码

匿名内部类示例

java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 实现接口
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类实现");
}
};

// 继承抽象类
Thread t = new Thread() {
@Override
public void run() {
System.out.println("继承Thread类");
}
};

Lambda表达式示例

java

1
2
3
4
5
6
7
8
9
10
11
12
// 无参数
Runnable r = () -> System.out.println("Lambda实现");

// 有参数
List<String> list = Arrays.asList("a", "b", "c");
list.forEach(item -> System.out.println(item));

// 多行代码
list.forEach(item -> {
String upper = item.toUpperCase();
System.out.println(upper);
});

注意事项

  1. Lambda表达式只能替代函数式接口的匿名内部类
  2. 当需要重写多个方法时,仍需使用匿名内部类
  3. Lambda表达式中的变量必须是final或事实上final
  4. 在需要访问实例变量或方法时,匿名内部类可能更合适