java - JDK8 javac/Eclipse Luna 类型推断的差异?

标签 java eclipse javac type-inference

我正在尝试将一个项目切换到 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 都能愉快地编译它:

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

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

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

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

C:\XXXX\Workspace\XXXX\src>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

最佳答案

编译器只能检查方法签名,不能检查方法体,因此这部分是无关紧要的。

这会将您的代码“减少”为(伪代码):

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> U getKey(...)真的是:<U extends Object> U getKey(...) .

它只知道 getKey(code, null)返回是:? extends Object , 所以它返回 Object 的子类型,或 Object本身。
匹配的签名有3个,分别是Object , char[]Throwable ,其中两个char[]ThrowableObject 同等且更好地匹配,因为你要求一个 ? extends Object .

所以它无法选择哪个是正确的,因为所有三个都匹配签名。

当您将其更改为:

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

然后只有public static String toString(Object obj);匹配,因为它与任何其他匹配更好 ? extends Object那不等于 Object .

编辑,我查看了问题的初衷:为什么它在 Java 7 中编译,而不是在 Java 8 中编译?

在 Java 8 中,类型推断得到了极大的改进。

而在 Java 7 中它只能推断出 getKey返回了 Object ,它现在在 Java 8 中推断它返回一个 ? extends Object .

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

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

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 ,正是因为我在上面概述的原因。

关于java - JDK8 javac/Eclipse Luna 类型推断的差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24868245/

相关文章:

javac 源和目标选项

javac 添加类路径破坏了我的本地类编译

java - 字符串数组类型变量的值不会更新(从另一个类引用时返回空)。 JavaFX

java - 对象 ='statutProduits' 验证失败。错误计数 : 2

eclipse - Ubuntu 64 位中的 SVNKit 或 JavaHL

java - AndroidManifest.xml FileNotFoundException?

Java 11 : What is the difference between javac --release and -source and -target command line parameters?

java - 使用数据报进行简单的客户端/服务器聊天数据包路由

java - 是否可以将 .class 文件添加到 URLClassLoader 的 urlpath 中

java - 在 Eclipse 中编译为 JAR(同时存在 GiT 存储库)