2016-03-22 10 views
3

ジェネリック医薬品とClassCastExceptionが

public class ClassCastTest { 

    private static class GenericHolder<T> { 
     private T object; 

     public GenericHolder(Object object) { 
      this.object = (T) object; 
      System.out.println(getObject()); 
     } 

     public T getObject() { 
      return object; 
     } 
    } 

    public static void main(String[] args) { 
     GenericHolder<String> foo = new GenericHolder<>(3l); 
     System.out.println(foo.getObject()); 
    } 

} 

なぜJavaは、代わりにGenericHolderの2行目のメイン・メソッドの2行目にClassCastExceptionをスローしますか?

+0

とにかくキャストはなぜですか?なぜそれがあなたが期待しているのであれば、Tをコンストラクタに渡すのはなぜですか? 'public GenericHolder(Tオブジェクト){this.object =オブジェクト; } ' – ManoDestra

+2

これは単なる例です;そのコードは必要ありません – Frame91

答えて

6

ジェネリックが言語で実装されているため、(T)へのキャストは実際には何も行いません。実際に具体的な型を取得する方法でジェネリック型を使用する場合のみです。ここでSystem.out.printlnStringを想定しており、それを取得するためのキャストを行います。実行時は実際にキャストを行います。

Javaランタイムに関する限り、GenericHolder<String>GenericHolder<Integer>の間に違いはありません。彼らは両方ともObjectを保持しています。 Javaは、ジェネリック型から具体的な型を取得するだけで、キャストを挿入するだけです。

研究type erasure詳細については、

+0

コンストラクタの2行目はまったく同じですか? System.out.printLnは文字列をまだ期待していますか? – Frame91

+1

はい、 'System.out.println((String)foo.getObject())'になります。キャストは実行され、キャストは失敗します。 –

+0

しかし、それはコンストラクタではなくメインでのみ例外をスローします - あなたの答えから得られるものは、メインメソッドのStringにキャストしようとし、コンストラクタで無視します。 – Frame91

2

ルイの答えに加えて、Tが書かれてTにキャストすることには、Tがバインドされている場合には「何か」があることを指摘すると便利です。あなたの代わりに

private static class GenericHolder<T extends CharSequence> 

を書く場合はCharSequenceLongをキャストすることはできませんので、例えば、その行

this.object = (T) object; 

は(、ClassCastExceptionを投げるん質問が3lないと言う注意31)。ただし、タイプTは実行時に認識されないため、その時点でStringにキャストしようとはしません。

+0

興味深い点! – Frame91

関連する問題