次のコード
public class GenericsTest2 {
public static void main(String[] args) throws Exception {
Integer i = readObject(args[0]);
System.out.println(i);
}
public static <T> T readObject(String file) throws Exception {
return readObject(new ObjectInputStream(new FileInputStream(file)));
// closing the stream in finally removed to get a small example
}
@SuppressWarnings("unchecked")
public static <T> T readObject(ObjectInputStream stream) throws Exception {
return (T)stream.readObject();
}
}
eclipseでコンパイルしますが、javacでコンパイルしません(Tの型パラメーターは判別できません。上限T、Java.lang.Objectを持つ型変数Tの一意の最大インスタンスは存在しません)。
ReadObject(String file)を変更すると
@SuppressWarnings("unchecked")
public static <T> T readObject(String file) throws Exception {
return (T)readObject(new ObjectInputStream(new FileInputStream(file)));
}
eclipseでjavacを使用してコンパイルします。 Eclipseコンパイラとjavacのどちらが正しいですか?
この場合、私はあなたのコードが間違っていると思います(そしてSunコンパイラは正しいです)。タイプreadObject
を実際に推測するためのT
への入力引数には何もありません。その場合は、Objectを返して、クライアントが結果の型を手動でキャストできるようにする方が良いでしょう。
これは動作するはずです(テストはしていませんが):
public static <T> T readObject(String file) throws Exception {
return GenericsTest2.<T>readObject(new ObjectInputStream(new FileInputStream(file)));
}
Oracle JDK6 u22は正しいはずですが、JDK6 u24でもこの問題があります
これはEclipseのバグです bug 98379 。
これは修正されませんでしたが、Eclipseバグの例のような回避策によって問題は解決されます(リンクを参照)
この問題はJavaバージョン "1.6.0_22"で見つかりました。アップデートで修正されたため、Javaバージョン "1.6.0_32"にアップグレードすると消えました。 25。
呼び出されたときに透過的に動作するようにメソッドreadObjectを変更できる場合は、次を使用することもできます。
public static <T> T readObject(String file, Class<T> type) throws Exception {
return type.cast(readObject(new ObjectInputStream(new FileInputStream(file))));
}
このようにして、呼び出し元は結果のタイプを指定するように強制され、コンパイラーは結果のキャスト方法を認識します。