Lambda表达式可以为函数式接口生成一个实例,然而lambda表达式并不包含它生成的函数式接口的信息,你需要知道lambda的实际类型是什么。
3.5.1 类型检查
Lambda的类型是从使用Lambda的上下文推断出来的。上下文(比如,接受它传递的方法的参数或接受它的值的局部变量)中Lambda 表达式所需要的类型为目标类型。
![[Pasted image 20241129170908.png]]

3.5.2 同样的Lambda,不同的函数式接口
有了目标类型的概念,同一个Lambda表达式就可以与不同的函数式接口联系起来,只有他们的抽象方法标签名能够兼容。
不同的函数式接口可以接收同一个Lambda表达式
Comparator<Integer> c1 = (o1, o2) -> o1.compareTo(o2);
BiFunction<Integer, Integer, Integer> c2 = (o1, o2) -> o1.compareTo(o2);
特殊的void兼容规则 : 如果一个Lambda的主体是一个语句表达式,它就和一个返回void的函数描述符兼容(当然需要参数列表也兼容)。
3.5.3 类型推断
3.5.4 使用局部变量
Lambda表达式也允许使用自由变量(不是参数,而是在外层作用域中的变量),就像匿名内部类一样,它们被称作捕获Lambda。
下面的Lambda表达式捕获了a变量
int a = 10;
Runnable runnable = () -> System.out.println(a);
Lambda可以没有限制地捕获(也就是其主体引用中的实例变量和静态变量),但被捕获的变量必须是实际最终变量。
实际最终变量指:被final修饰的变量,或实际上只赋值过一次的变量。
下面的代码是错误的
int a = 10;
Runnable runnable = () -> System.out.println(a);
a = 20;
错误信息 :
java: 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量

1049

被折叠的 条评论
为什么被折叠?



