java在类型推断上的差异JDK8 javac/Eclipse Luna?
我试图将一个项目切换到Java8,但在EclipseLuna和javac的类型推断之间遇到了奇怪的差异。使用JDK 1.7.0_65 javac,这段代码可以很好地编译。JDK 1.8.0_11抱怨toString(char[])和toString(Throwable)都与“toString(getKey(code,null));”匹配线EclipseLuna 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(对象)
当然,我可以简单地向对象添加一个cast,但我想知道为什么javac不能自己推断类型(而eclipse可以),为什么heck javac认为Throwable和char[]匹配,而不是Object
这是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
# 1 楼答案
编译器只能检查方法签名,而不能检查方法体,因此部分是无关的
这将“减少”您的代码为(psuedocode):
还要注意
<U> U getKey(...)
实际上是:<U extends Object> U getKey(...)
它只知道
getKey(code, null)
返回的是:? extends Object
,所以它返回Object
的一个子类型,或者Object
本身有三个匹配的签名,即
Object
、char[]
和Throwable
,其中char[]
和Throwable
匹配相同,并且比Object
更好,因为您要求的是? extends Object
因此,它无法选择哪个是正确的,因为这三个都与签名匹配
当您将其更改为:
然后只有
public static String toString(Object obj);
匹配,因为它比其他不等于Object
的? extends Object
匹配得更好编辑,我查看了这个问题的初衷:为什么它是用Java 7编译的,而不是用Java 8编译的
在Java8中,类型推断得到了极大的改进
例如,在Java 7中,它只能推断
getKey
返回一个Object
,而在Java 8中,它现在推断它返回一个? extends Object
使用Java7时,只有一个匹配项,即^{
<> P>为了使变化更加形象化,请考虑这段代码:在Java 7上它打印
1
,在Java 8上它打印2
,正是因为我上面概述的原因