给出以下代码:
package com.gmail.oksandum.test; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { } public void foo() { class LocalFoo { LocalFoo(String in) { //Some logic } } List<String> ls = new ArrayList<>(); ls.stream().map(LocalFoo::new); //Line 21 } }
我的IDE没有给我任何错误。也就是说,直到我尝试构建项目并运行它。当我这样做时,它给了我一个看起来像这样的编译器错误:
Error:(21, 24) java: incompatible types: cannot infer type-variable(s) R (argument mismatch; invalid constructor reference cannot access constructor LocalFoo(java.lang.String) an enclosing instance of type com.gmail.oksandum.test.Test is not in scope)
现在,我得到了错误消息,如果foo()是静态的,则不会发生这种情况。没错,这仅在foo()是实例方法的情况下才会发生。并且仅当LocalFoo是实例方法中的本地类时才发生,并且仅当使用构造函数引用时(即从不使用常规方法引用)才发生。
更重要的是,如果我将第21行更改为
ls.stream().map(str -> new LocalFoo(str));
编译器突然没有给出错误。
因此,回顾一下。如果我尝试在实例方法中声明的本地类上使用构造函数引用,则编译器会抱怨无法访问构造函数,对此我感到困惑。
如果有人可以阐明为什么会发生这种情况,将不胜感激。谢谢。
看起来好像LocalFoo以某种方式被视为非静态类。这就是为什么它声称没有Test实例在范围内的原因。
LocalFoo
从教程中:
局部类是非静态的,因为它们可以访问封闭块的实例成员。因此,它们不能包含大多数静态声明。
https://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html
该方法foo()或类LocalFoo必须是静态的才能起作用。但是方法内的类不能声明为静态。因此,如果foo()应该保持非静态(作为内部静态类),则必须将其移出方法。另一种选择是仅使用此: ls.stream().map(s -> new LocalFoo(s));
foo()
ls.stream().map(s -> new LocalFoo(s));
应该有一种只说的方法Test.this.LocalFoo,但这是行不通的。如果这样做,编译器也应该接受LocalFoo::new。
Test.this.LocalFoo
LocalFoo::new