使用本地类时无效的构造函数引用?
给出以下代码:
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 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
在某种程度上被视为非静态类。 这就是为什么它声称没有测试的实例在范围内。
从教程:
本地类是非静态的,因为它们可以访问封闭块的实例成员。 因此,它们不能包含大多数类型的静态声明。
https://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html
方法foo()
或类LocalFoo
必须是静态的才能工作。 但是方法中的类不能声明为static。 因此,如果foo()
应保持非静态(作为内部静态类),则必须将其移出方法。 另一种选择是使用它:
ls.stream().map(s -> new LocalFoo(s));
应该有一种方法可以说Test.this.LocalFoo
,但这不起作用。 如果确实如此,编译器也应该只接受LocalFoo::new
。
现在有一个错误报告: https : //bugs.openjdk.java.net/browse/JDK-8144673
(见Brian Goetz的评论 )
一个问题是你试图通过在列表中指定generics类型来实例化Arraylist,但是在Arraylist中不使用相同的类型。
使用:List ls = new ArrayList();
另请为LocalFoo提供默认构造函数