29

给定以下代码:

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));

编译器突然没有错误。

所以回顾一下。如果我尝试在实例方法中声明的本地类上使用构造函数引用,编译器会抱怨无法访问构造函数,对此我感到困惑。

如果有人可以阐明为什么会发生这种情况,将不胜感激。谢谢。

4

2 回答 2

6

看起来好像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 (参见Brian Goetz 的评论

于 2015-11-29T12:35:51.733 回答
-5

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

使用:列表 ls = new ArrayList();

还请为 LocalFoo 提供默认构造函数

于 2014-10-15T06:36:33.850 回答