Java 使用本地类时构造函数引用无效?

Java 使用本地类时构造函数引用无效?,java,lambda,java-8,method-reference,constructor-reference,Java,Lambda,Java 8,Method Reference,Constructor Reference,给定以下代码: 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) {

给定以下代码:

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
    }

}
现在,我想,如果给出错误消息,如果foo()是静态的,就不会发生这种情况。非常正确,只有当foo()是一个实例方法时,才会发生这种情况。只有当LocalFoo是实例方法中的一个本地类,并且仅当使用了构造函数引用(即从不使用常规方法引用)时,才会发生这种情况

而且,如果我把第21行改成

ls.stream().map(str -> new LocalFoo(str));
编译器突然没有给出错误

总而言之。如果我试图对实例方法中声明的本地类使用构造函数引用,编译器会抱怨无法访问构造函数,对此我感到困惑

如果有人能解释为什么会发生这种情况,我们将不胜感激。
谢谢。

一个问题是,您试图通过在列表中指定泛型类型来实例化Arraylist,但没有在Arraylist中使用相同的类型

使用: List ls=新的ArrayList()


另外,请为LocalFoo提供一个默认构造函数,它看起来像是
LocalFoo
被视为一个非静态类。这就是为什么它声称范围内没有测试实例

在本教程中:

局部类是非静态的,因为它们可以访问封闭块的实例成员。因此,它们不能包含大多数类型的静态声明

方法
foo()
或类
LocalFoo
必须是静态的才能工作。但是方法中的类不能声明为静态的。因此,如果
foo()
应保持非静态(作为内部静态类),则必须将其移出方法。 另一种选择是只使用此选项:
ls.stream().map->newlocalfoo(s))

应该有一种方法只说
Test.this.LocalFoo
,但这不起作用。如果是这样,编译器也应该只接受
LocalFoo::new

现在有一个错误报告:

(请参阅)

意味着应该编译对本地类的构造函数引用(该错误是与使用继承的本地类相关的运行时错误)。局部类通常看起来杂乱无章且未指定。@Rocoty:构造函数引用用于什么?构造一个对象。为了构造这样一个本地类的实例,需要一个外部类的实例,因此,构造函数有一个外部类类型的额外的不可见参数。由编译器使用当前外部类实例填充该参数,该实例在使用普通
new
表达式时有效,但在方法引用时失败。我猜,这是因为那个令人困惑的规则。@Rocoty:这是个大问题。在阅读了大量的规范之后,我仍然不确定是否有可能说它是否违反了规范。但我认为,它应该是有效的,或者应该在规范中添加一个明确的声明“不是有意的”,毕竟,我不认为有理由否认这个特性。因此,最好的做法是提交一份bug报告,即使规范中没有可引用的部分。如果该报告以“not a bug”结尾,那么,至少我们有了答案。同样的代码在我的PC(ubuntu 14.04、Eclipse Luna和jdk1.8.0_20)上编译并完美运行,没有错误LocalFoo类是一个非静态类,需要一个封闭的实例。(从JDK编译器得到的错误比Eclipse错误更清楚。)错误在于编译器找不到实例,就像在普通非静态内部类中一样;当提供一组空括号时,编译器推断参数类型与引用类型中指定的参数类型相同。当然,我可以不使用泛型类型来尝试此操作,但我认为您可能忽略了问题的本质。使用原始类型
列表
只会添加另一个错误(
对象无法转换为字符串
)。为LocalFoo添加默认构造函数并不能解决此错误(因为由于算术不匹配,您无法将默认构造函数用作
函数
参数映射到
map
)。建议使用原始类型是一个坏主意,因为您规避了泛型的类型安全性。我建议您阅读Java 7中添加的菱形操作符。我还看到Eclipse接受不应该接受的代码。您可以通过尝试OpenJDK命令行编译器,或者查找确认为Eclipse错误的Eclipse错误报告来改进这个答案。我已经完全改写了答案。我只是做了一些测试。这个问题似乎只针对实例方法中的局部类。事实上,它是一个非静态类是不相关的;我运行了一个测试,其中我声明LocalFoo是一个非静态的内部类,并且没有收到编译器的抱怨。如果内部类是方法的本地类,编译器似乎无法推断外部类型的“隐藏”参数,即使如果内部类不是本地类,编译器也可以推断参数。这就是为什么我认为这是java编译器中的一个bug,而不是任何IDE中的bug。所以问题是:这是一个已知bug吗?是否有bug报告?我什么也没找到
ls.stream().map(str -> new LocalFoo(str));