/ /なぜこのジェネリックキャストは失敗しないのですか? - ジャワ、ジェネリック、キャスティング

なぜこのジェネリックキャストは失敗しないのですか? - java、ジェネリック、キャスト

このコードでClassCastExceptionがスローされることを期待します。

public class Generics {
public static void main(String[] args) {
method(Integer.class);
}

public static <T> T method(Class<T> t) {
return (T) new String();
}
}

しかし、返されたオブジェクトをなんらかの方法で使用するまで、TへのStringのキャストは失敗しません。

public class Generics {
public static void main(String[] args) {
method(Integer.class).intValue();
}

public static <T> T method(Class<T> t) {
return (T) new String();
}
}

背景:私はJAXBを使用してXMLファイルを非整列化するクラスを作成しました。それはこのように見えます:

public static <T> T unmarshal(File file, Class<? extends T> clazz)

ルート要素が匿名型かどうかに関係なく、TまたはJAXBElementが返されます。 JAXBElementはもちろん、Tにキャストすることはできません。 結果を処理せずにunmarshal()を呼び出しただけの単体テストでは、すべてうまくいきました。コードでは、それは失敗しました。

直接失敗しないのはなぜですか?これはバグですか?そうでなければ、私はその理由を理解したいです。

回答:

回答№1は4

明示的に指定されていないので、TはObjectです。

だからルックアップはこんな感じ

public class Generics {

public static void main(String[] args) {
Generics.method(Integer.class).intValue();
}

public static Object method(Class<Object> t) {
return (Object) new String();
}
}

総称パラメーターを指定すると、

public class Generics {

public static void main(String[] args) {
Generics.<Integer>method(Integer.class).intValue();
}

public static <T> T method(Class<T> t) {
return (T) new String();
}
}

あなたはその例外を受けるでしょう。


回答№2については4

Tが明示的に指定されていない場合、タイプ消去はそれをそれとして扱います。 Object。そのため、Stringオブジェクトはキャストできます。


回答№3の場合は1

私はあなたがこのようにより強いメソッド定義を作ることができると思います:

public static <T extends Number> T method(Class<T> t) {
return //// some code.
}

この場合、line return new String()はコンパイルできません。

しかしlineはnew Integer(123)を返します。コンパイルされ、動作し、キャストは必要ありません。