Eclipse Neon

时间:2017-07-06 06:25:44

标签: java eclipse generics lambda eclipse-neon

大家早上好,

我已经挣扎了一段时间,理解为什么以下的代码片段不能在Eclipse Neon(JDT 3.12.3.v20170301-0400)中编译,但与javac或Eclipse Mars完美编译:

public class TestLambda {

    protected static <K, V> Map<K, V> newMap(final Function<K, V> loader) {
        return new HashMap<>();
    }

    private final Map<Integer, Integer> working = newMap(key -> {

        final List<String> strings = new ArrayList<>();

        final String[] array = strings.toArray(new String[strings.size()]);
        foo(array);

        return null;
    });

    private final Map<Void, Void> notWorking = newMap(key -> {

        final List<String> strings = new ArrayList<>();

        // This line seems to be the root of all evils
        foo(strings.toArray(new String[strings.size()]));

        return null;
    });

    private void foo(final String[] x) {}

    private void foo(final Integer[] x) {}

}

Eclipse编译器说&#34;类型不匹配:无法从Map<Object,Object>转换为Map<Void,Void>&#34;。

似乎无法知道必须调用哪个foo方法......

我做错了吗?

提前感谢您的帮助

1 个答案:

答案 0 :(得分:0)

即使使用最新版本的Eclipse Oxygen,我也可以重现这个问题。任何{8}版本的Java 8或Java 9 beta都不会出现此问题。

我们可以清楚地得出结论,这是一个错误和一个奇怪的错误。

首先,这里没有歧义。 javac的两次调用都必须以foo结束,事实上,Eclipse不会报告歧义问题。

其次,foo(String[])调用对此lambda表达式的功能类型没有影响。

如果我们将行foo更改为foo(strings.toArray(new String[strings.size()]));,我们会在foo(strings.toArray());处收到真正的错误,因为不存在foo,但类型推断会正确解析{{ 1}}表示lambda表达式,foo(Object[])表示Function<Void, Void>的返回类型。

我们还可以通过将Map<Void, Void>声明更改为

来创建真正的歧义问题
newMap

这会导致foo次调用都出错,因为private void foo(final Serializable[] x) {} private void foo(final CharSequence[] x) {} 与这两种方法兼容,fooString[]之间没有关系,但是类型推断Serializable调用未受影响并解析为
CharSequence正如所料。

最奇怪的是,只需交换newMap方法的顺序就会使错误消失:

<Void, Void> Map<Void, Void> newMap(Function<Void, Void>)

编译好。

背后有一种模式。只要最后声明的一个适用foo调用,您就可以拥有所需的public class TestLambda { protected static <K, V> Map<K, V> newMap(final Function<K, V> loader) { return new HashMap<>(); } private final Map<Integer, Integer> working = newMap(key -> { final List<String> strings = new ArrayList<>(); final String[] array = strings.toArray(new String[strings.size()]); foo(array); return null; }); private final Map<Void, Void> notWorking = newMap(key -> { final List<String> strings = new ArrayList<>(); // This line seems to be the root of all evils foo(strings.toArray(new String[strings.size()])); return null; }); private void foo(final Integer[] x) {} private void foo(final String[] x) {} } 次重载。它不必是最终调用的最具体的一个,例如,在课程结束时放置另一个foo也将解决问题。

该模式肯定没有匹配的Java语言规则......

相关问题