为什么java 8 lambdas允许访问非final类变量?
发布时间:2020-12-15 00:46:40 所属栏目:Java 来源:网络整理
导读:参见英文答案 Local class can access non-final variable in java 81个 Lambdas: local variables need final,instance variables don’t9个 我理解为什么编译器不接受以下内容: class Foo { public SupplierString makeSupplier() { String str = "hello"
参见英文答案 >
Local class can access non-final variable in java 81个
> Lambdas: local variables need final,instance variables don’t9个 我理解为什么编译器不接受以下内容: class Foo { public Supplier<String> makeSupplier() { String str = "hello"; Supplier<String> supp = () -> return str; // gives the expected compile error because // str is not effectively final // (str is a local variable,compile-time error // as per JLS 15.27.2.) str = "world"; return supp; } } 令我困惑的是编译器接受以下内容,并且单元测试通过: class Bar { private String str = "hello"; public void setStr(String str) { this.str = str; } public Supplier<String> makeSupplier() { Supplier<String> supp = () -> { return str; }; return supp; } @Test public void Unit_lambdaCapture() { Supplier<String> supp = makeSupplier(); Assert.assertEquals(supp.get(),"hello"); setStr("foo"); Assert.assertEquals(supp.get(),"foo"); } } 为什么上述有效且正常工作?欢迎使用JLS相关部分的指针(第15.27.2节,仅讨论局部变量). 解决方法
我们都同意第一个例子不起作用,因为局部变量或参数必须在
lambda expression body中使用
final or effectively final.
但是你的第二个例子不涉及局部变量或参数,因为str是一个实例字段. Lambda表达式可以像实例方法一样访问实例字段: 15.27.2. Lambda Body
事实上,java编译器从lambda表达式中创建一个私有方法lambda $0,它只是访问实例字段str: private java.lang.String lambda$0() { 0 aload_0; /* this */ 1 getfield 14; /* .str */ 4 areturn; } 另一种观点:您还可以使用普通的匿名内部类来实现供应商: public Supplier<String> makeSupplier() { return new Supplier<String>() { public String get() { return str; } }; } 从内部类访问实例字段非常常见,而不是Java 8的专业. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |