这个问题已经在这里有一个答案:
- Java类型推理:基准是不明确的在Java中8,但不是Java 7个 2答案
任何人都不会明白,为什么下面的代码将在Java 7中及以下编译罚款,但未能与Java 8。
public static void main(String[] args) throws Exception {
put(get("hello"));
}
public static <R> R get(String d) {
return (R)d;
}
public static void put(Object o) {
System.err.println("Object " + o);
}
public static void put(CharSequence c) {
System.err.println("CharSequence " + c);
}
public static void put(char[] c) {
System.err.println("char[] " + c);
}
get方法有一个通用的返回类型。 在JDK 7和低于该编译好并且选择与该对象参数的put方法。 在JDK 8这不能被编译,说明put方法是不明确的。
显然JDK 8跳过对象参数的方法,并找到最后两个子对象的参数的方法和抱怨他们(也就是说,如果你与其他一些参数类型添加其他put方法,编译器会切换并抱怨新的最后两种方法)
这似乎是一个错误。
你的问题是广义靶式推理 ,在Java 8的改进的副作用。
什么是目标型推理
让我们把你方法的例子,
public static <R> R get(String d) {
return (R)d;
}
现在,在上述方法中,泛型参数R
不能由编译器,因为有不带参数解析R
因此,他们引入了一个概念叫Target-type Inference
,它允许基于分配参数来推断的参数。
所以,如果你这样做,
String str = get("something"); // R is inferred as String here
Number num = get("something"); // R is inferred as Number here
这适用于Java 7中,但以下情况不 ,
put(get("something");
static void Put(String str) {} //put method
由于类型推断只是工作的直接分配。
如果没有直接分配,那么泛型类型被推断为Object
。
所以,当你的Java 7编译的代码,你put(Object)
方法的调用没有任何问题。
他们在Java中没有8
他们改进了类型推断推断方法调用和链接的方法调用的类型
关于他们的更多细节在这里和这里
所以,现在,你可以直接调用put(get("something"))
和通用型将根据的参数来推断 put()
方法 。
但你也知道,方法, put(Charsequence)
和put(char[])
相匹配的参数。 因此,有歧义。
固定?
只是告诉你想要什么编译器,
put(TestClass.<CharSequence>get("hello")); // This will call the put(CharSequence) method.
看起来这是一个已知的不兼容。
参见“区域:工具/ javac的”部分这篇文章。 而这个bug 。
概要
下面的代码,其编译,以警告,在JDK 7在JDK 8不会编译:
import java.util.List;
class SampleClass {
static class Baz<T> {
public static List<Baz<Object>> sampleMethod(Baz<Object> param) {
return null;
}
}
private static void bar(Baz arg) {
Baz element = Baz.sampleMethod(arg).get(0);
}
}
在JDK 8编译此代码产生以下错误:
SampleClass.java:12: error:incompatible types: Object cannot be converted to Baz
Baz element = Baz.sampleMethod(arg).get(0);
Note: SampleClass.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
在这个例子中,原始类型被传递给其可应用于由子类型的sampleMethod(巴兹)方法(见JLS,爪哇SE 7版,部分15.12.2.2)。
一个未经检查的转换是必要的方法是适用的,所以它的返回类型被擦除(见JLS,爪哇SE 7版,部分15.12.2.6)。 在这种情况下sampleMethod(巴兹)的返回类型是java.util.List的代替的java.util.List>从而得到(INT)的返回类型为对象,这是不分配兼容巴兹。