JDK8 javac/Eclipse Luna 类型推断的差异? [英] Differences in type inference 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
本身.
有三个匹配的签名,分别是Object
、char[]
和Throwable
,其中char[]
和Throwable
与 Object
的匹配度相同且更好,因为您要求的是 ?扩展对象
.
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屋!