【Java异常】Variable used in lambda expression should be final or effectively final
【Java异常】Variable used in lambda expression should be final or effectively final
从字面上来理解这句话,意思是:*lambda表达式中使用的变量应该是final或者有效的final*,也就是说,lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
要求外部变量为final是在编译期以强制手段确保用户不会在lambda表达式中做修改原变量值的操作。
其实在Java8之前,匿名类中如果要访问局部变量的话,那个局部变量必须显式的声明为final。
Demo代码示例:
package com.example.core.mydemo.java8; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class Java8FinalTest { public static void main(String[] args) { //如果直接定义变量,不会报错”Variable used in lambda expression should be final or effectively final“ // List<Integer> number = Arrays.asList(1,2,3,4,5,6,7,8,9,10); //如果分开赋值,就会报错”Variable used in lambda expression should be final or effectively final“ List<Integer> number = null; number = Arrays.asList(1,2,3,4,5,6,7,8,9,10); //创建临时中间变量,可以用final也可以不用final final List<Integer> numberTmp = number; //Variable used in lambda expression should be final or effectively final List<Integer> group = Arrays.asList(1,2); List<Object> groupResult = group.stream().map(x -> calc(numberTmp)).collect(Collectors.toList()); groupResult.stream().forEach(System.out :: println); //匿名内部类 1.8不会报错 //1.7会报错:Variable 'jdkVersion' is accessed from within inner class, needs to be declared final,意思是:变量‘dkVersion’在匿名内部类中被访问,必须被声明为final类型的。 String jdkVersion = "1.7"; testFinal(new Suppliers(){ @Override public String get() { return jdkVersion; } }); } public static void testFinal(Suppliers supplier){ System.out.println("supplier=" + supplier.get()); } private static Object calc(List<Integer> number) { //变量不允许修改 // number.add(11); Exception in thread "main" java.lang.UnsupportedOperationException return number.stream().mapToInt(x -> x).sum(); } static class Suppliers{ public String get(){ return "hello world"; } } }