Dur*_*dal 6 java eclipse type-inference javac
我正在尝试将项目切换到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));
}
}
Run Code Online (Sandbox Code Playgroud)
我认为唯一可能匹配的签名是toString(Object).
当然我可以简单地向Object添加一个强制转换,但我想知道为什么 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
Run Code Online (Sandbox Code Playgroud)
编译器只能检查方法签名,而不能检查方法主体,因此该部分是不相关的。
这将您的代码“减少”为(伪代码):
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));
}
}
Run Code Online (Sandbox Code Playgroud)
另请注意,<U> U getKey(...)实际上是:<U extends Object> U getKey(...)。
它只知道getKey(code, null)返回的是:? extends Object,因此它返回 的子类型Object,或者它Object本身。
有 3 个匹配的签名,即Object、char[]和Throwable,其中 和char[]都Throwable匹配并且比 匹配得更好Object,因为您要求的是? extends Object。
因此它无法选择哪一个是正确的,因为所有三个都与签名匹配。
当你将其更改为:
public static Object getKey(Object code, Object defaultValue);
Run Code Online (Sandbox Code Playgroud)
then 只public static String toString(Object obj);匹配,因为它比任何其他不等于 的匹配更好。? extends ObjectObject
编辑,我查看了问题的初衷:为什么它可以在 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();
}
}
Run Code Online (Sandbox Code Playgroud)
在 Java 7 上它打印1,在 Java 8 上它打印2,正是因为我上面概述的原因。