给出以下代码:

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实例在范围内的原因。

从教程中:



https://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html

方法foo()或类LocalFoo必须是静态的才能起作用。但是不能将方法内部的类声明为静态的。因此,如果foo()应该保持非静态(作为内部静态类),则必须将其移出方法。
另一种选择是仅使用此:ls.stream().map(s -> new LocalFoo(s));
应该有一种只说Test.this.LocalFoo的方法,但这不起作用。如果这样做的话,编译器也应该只接受LocalFoo::new

现在有一个错误报告:https://bugs.openjdk.java.net/browse/JDK-8144673
(请参阅comment by Brian Goetz)

10-04 12:29