次のコードが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以前では、これは正常にコンパイルされ、Objectパラメーターを使用したputメソッドが選択されます。 JDK 8ではこれをコンパイルできず、putメソッドがあいまいであることを示しています。
どうやらJDK 8はオブジェクトパラメータメソッドをスキップして最後の2つのサブオブジェクトパラメータメソッドを見つけて不平を言っています(つまり、別のパラメータタイプで別のputメソッドを追加すると、コンパイラは新しい最後の2つの方法)
これはバグのようです。
あなたの問題は一般化されたターゲット型推論の副作用で、Java 8。
例の方法を見てみましょう。
_public static <R> R get(String d) {
return (R)d;
}
_
さて、上記のメソッドでは、R
を持つパラメーターがないため、汎用パラメーターR
をコンパイラーで解決できません。
そのため、彼らは_Target-type Inference
_という概念を導入しました。これにより、割り当てパラメーターに基づいてパラメーターをinferredにできます。
だから、もしそうなら、
_ 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)
メソッドは問題なく呼び出されました。
彼らはtype inferenceを改良して、method callsおよびchained method callsから型を推測しました。
したがって、put(get("something"))
を直接呼び出すことができ、ジェネリック型はput()
メソッドのパラメーターに基づいてinferredになります。
ただし、ご存じのとおり、メソッドput(Charsequence)
およびput(char[])
は引数と一致します。そのため、あいまいさがあります。
コンパイラに必要な情報を正確に伝えるだけで、
_put(TestClass.<CharSequence>get("hello")); // This will call the put(CharSequence) method.
_
これは既知の非互換性のようです。
この記事 および このバグ の「Area:Tools/javac」セクションを参照してください。
あらすじ
警告付きで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(Baz)メソッドに渡されていますが、これはサブタイピングによって適用できます(JLS、Java SE 7 Edition、セクション15.12.2.2を参照)。
メソッドを適用するには未チェックの変換が必要であるため、その戻り値の型は消去されます(JLS、Java SE 7 Edition、セクション15.12.2.6を参照)。この場合、戻り値の型はsampleMethod(Baz)はJava.util.List>ではなくJava.util.Listであるため、get(int)の戻り値の型はObjectであり、Bazとの割り当て互換性はありません。