JDK8 javac/Eclipse Luna 类型推断的差异? [英] Differences in type inference JDK8 javac/Eclipse Luna?

查看:26
本文介绍了JDK8 javac/Eclipse Luna 类型推断的差异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将项目切换到 Java8,但遇到了 Eclipse Luna 和 javac 的类型推断之间的奇怪差异.使用 JDK 1.7.0_65 javac 这段代码编译得很好.JDK 1.8.0_11 抱怨 toString(char[]) 和 toString(Throwable) 都匹配toString(getKey(code, null));"线.Eclipse Luna 4.4 (I20140606-1215) 可以使用 JDK 愉快地编译它:

I'm trying to switch a project to Java8, and encounter odd differences between Eclipse Luna and javac's type inference. With JDK 1.7.0_65 javac this code compiles just fine. JDK 1.8.0_11 complains that both toString(char[]) and toString(Throwable) match for the "toString(getKey(code, null));" line. Eclipse Luna 4.4 (I20140606-1215) compiles it happily with either JDK:

public class TypeInferenceTest {
    public static String toString(Object obj) {
        return "";
    }

    public static String toString(char[] ca) {
        return "";
    }

    public static String toString(Throwable t) {
        return "";
    }

    public static <U> U getKey(Object code, U defaultValue) {
        return defaultValue;
    }

    public static void test() {
        Object code = "test";
        toString(getKey(code, null));
    }
}

我认为唯一可能匹配的签名是 toString(Object).

I think the only signature that could possibly match is toString(Object).

当然我可以简单地向 Object 添加一个强制转换,但我想知道 为什么 javac 不能自己推断类型(而 eclipse 可以),以及为什么 javac 认为 Throwable 和 char[] 合适的匹配,但不是 Object.

Of course I could simply add a cast to Object, but I wonder why javac can't infere the type by itself (while eclipse does), and why the heck javac considers Throwable and char[] suitable matches, but not Object.

这是 Eclipse 还是 javac 中的错误?(我的意思是这里只能有一个编译器,要么编译要么不编译)

Is this a bug in Eclipse or javac? (I mean only one compiler can be right here, either it compiles or it doesn't)

来自 javac (JDK8) 的错误消息:

Error message from javac (JDK8):

C:XXXXWorkspaceXXXXsrc>javac -cp . TypeInferenceTest.java
TypeInferenceTest.java:22: error: reference to toString is ambiguous
                toString(getKey(code, null));
                ^
  both method toString(char[]) in TypeInferenceTest and method toString(Throwable) in TypeInferenceTest match
1 error

推荐答案

编译器只能检查方法签名,不能检查方法体,所以这部分无关紧要.

Compilers can only inspect the method signatures, not the method body, so that part is irrelevant.

这将您的代码减少"为(伪代码):

This "reduces" your code to (psuedocode):

public class TypeInferenceTest {
    public static String toString(Object obj);

    public static String toString(char[] ca);

    public static String toString(Throwable t);

    public static <U> U getKey(Object code, U defaultValue);

    public static void test() {
        Object code = "test";
        toString(getKey(code, null));
    }
}

还要注意 U getKey(...) 实际上是: U getKey(...).

Also note that the <U> U getKey(...) really is: <U extends Object> U getKey(...).

它所知道的 getKey(code, null) 返回的是: ?扩展 Object,因此它返回 Object 的子类型,或 Object 本身.
有三个匹配的签名,分别是Objectchar[]Throwable,其中char[]ThrowableObject 的匹配度相同且更好,因为您要求的是 ?扩展对象.

All it knows that getKey(code, null) returns is: ? extends Object, so it returns a subtype of Object, or an Object itself.
There are three signatures that match, namely Object, char[] and Throwable, where both char[] and Throwable match equally and better than Object, because you asked for an ? extends Object.

所以它不能选择哪个是正确的,因为所有三个都匹配签名.

So it cannot choose which is the correct one, because all three match the signature.

当您将其更改为:

public static Object getKey(Object code, Object defaultValue);

那么只有 public static String toString(Object obj); 匹配,因为它与任何其他 匹配更好?扩展对象 不等于Object.

then only public static String toString(Object obj); matches, because it matches better as any other ? extends Object that is not equal to Object.

编辑,我看了一下问题的原意:为什么它在Java 7中编译,而不是在Java 8中编译?

Edit, I looked over the original intent of the question: Why does it compile in Java 7, but not in Java 8?

在 Java 8 中类型推断得到了很大的改进.

In Java 8 type inference got greatly improved.

例如,在 Java 7 中它只能推断 getKey 返回一个 Object,而现在在 Java 8 中它推断它返回一个 ?扩展对象.

Whereas in Java 7 it could for example only infer that getKey returned an Object, it now in Java 8 infers that it returns an ? extends Object.

当使用 Java 7 时,只有 一个 匹配,即 Object.

When using Java 7 there was only one match, namely Object.

为了更好地可视化更改,请考虑以下代码:

To have the change visualized even better, consider this piece of code:

public class TypeInferenceTest {
    public static String toString(Object obj) { return "1"; }

    public static String toString(Throwable t) { return "2"; }

    public static <U> U getKey(Object code, U defaultValue) { return defaultValue; }

    public static void test() {
        Object code = "test";
        String result = toString(getKey(code, null));
        System.out.println(result);
    }

    public static void main(String[] args) {
        test();
    }
}

在 Java 7 上它打印 1,在 Java 8 上它打印 2,正是因为我上面概述的原因.

On Java 7 it prints 1, on Java 8 it prints 2, exactly because of the reasons I have outlined above.

这篇关于JDK8 javac/Eclipse Luna 类型推断的差异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆