2010-11-19 20 views
5

私はこのコード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にキャストするのは失敗しません。

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(); 
    } 
} 

背景:XMLファイルを非整列化するためにJAXBを使用するクラスを作成しました。次のようになります。

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

root-Elementが匿名型であるかどうかによって、TまたはJAXBElementが返されます。もちろん、JAXBElementはTにキャストすることはできません。 私のユニットテストでは、結果を使って何もせずにunmarshal()を呼び出すだけで、すべて正常に動作しました。コードでは、失敗しました。

なぜそれは直接失敗しないのですか?これはバグですか?そうでない場合は、理由を理解したいと思います。

+1

まあ、警告します*。 – Jeremy

答えて

4

明示的に指定しないので、Tはオブジェクトです。あなたは一般的なパラメータを指定した場合

だからこの

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(); 
    } 
} 

あなたは、その例外が発生します。

4

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

1

私はあなたがこのような強力なメソッド定義を作ることができると思います。この場合、行には

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

(新しいStringを返す)だけでコンパイルすることはできません。

ただし、改行改行整数(123)。コンパイルされ、動作し、キャストする必要はありません。