Java は、多くの場合、引数に基づいてジェネリックを推論できます (たとえば、C# とは対照的に、戻り値の型に基づいても)。
Pair<T1, T2>
適切な例: 値のペアを格納するだけで、次の方法で使用できるジェネリック クラスがあります。
Pair<String, String> pair = Pair.of("Hello", "World");
メソッドof
は次のようになります。
public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
return new Pair<T1, T2>(first, second);
}
非常に素晴らしい。ただし、これは、ワイルドカードが必要な次のユースケースでは機能しなくなりました。
Pair<Class<?>, String> pair = Pair.of((Class<?>) List.class, "hello");
List.class
(正しい型を作成するための明示的なキャストに注意してください。)
コードは次のエラーで失敗します (Eclipse によって提供されます)。
TestClass.Pair<Class<capture#1-of ?>,String>
型の不一致: からに変換できませんTestClass.Pair<Class<?>,String>
ただし、コンストラクターを明示的に呼び出すと、期待どおりに機能します。
Pair<Class<?>, String> pair =
new Pair<Class<?>, String>((Class<?>) List.class, "hello");
誰かがこの振る舞いを説明できますか? それは設計によるものですか?欲しいですか?私は何か間違ったことをしていますか、それとも設計上の欠陥やコンパイラのバグに遭遇しましたか?
勝手な推測: 「capture#1-of ?」どういうわけか、ワイルドカードがコンパイラによってオンザフライで埋められ、型が aClass<List>
になり、変換が失敗することを暗示しているようです (からPair<Class<?>, String>
へPair<Class<List>, String>
)。これは正しいですか?これを回避する方法はありますか?
Pair
完全を期すために、クラスの簡略化されたバージョンを次に示します。
public final class Pair<T1, T2> {
public final T1 first;
public final T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
return new Pair<T1, T2>(first, second);
}
}