2016-04-08 9 views
2

を使用してキャストします。このブロックコードは ジェネリックは、私は次のことを理解しようとしたカッコ

[email protected] 
[email protected] 

次を出力しますので、私は、キャストが正常に完了したと仮定し、私は、リスト内の第二の目的のためにClassCastExceptionが期待しています。

public class TestGenerics 
{ 
    public static void main(String[] args) 
    { 
     Generic<One> integerGeneric = new Generic<One>(new Container(Lists.<Object>newArrayList(new One(), new Two()))); 
     integerGeneric.checkContainer(); 
    } 

    static class Generic<T> 
    { 
     private Container container; 

     public Generic(Container container) 
     { 
      this.container = container; 
     } 

     public void checkContainer() 
     { 
      for (Object key : container.getObjects()) 
      { 
       final T genericKey = (T)key; 
       System.out.println(genericKey); 
      } 
     } 
    } 

    static class Container 
    { 
     Iterable<Object> objects; 

     public Container(Iterable<Object> objects) 
     { 
      this.objects = objects; 
     } 

     public Iterable<Object> getObjects() 
     { 
      return objects; 
     } 
    } 

    static class One 
    { 

    } 

    static class Two 
    { 

    } 
} 

P.S. はまた、私は、一般的な型キャスト((T)オブジェクトを使用して)が代わりに例外をスローClassCastExceptiongのnullを返すという問題に直面したが、私はそれを再現傾けます。誰もがこのことを知った場合は、ここでコメントしてください、

+1

あなたは「型消去」は何であるか、それはJavaでどのように機能するかをルックアップする場合があります。 – Tom

+0

私はそこにチェックされていないキャスト警告があることを賭けるつもりです。 –

+0

@Tom、おかげで、私は(それが「存在」がある場合、または最寄りのタイプ)JVMは、オブジェクトの実行時における型のような一般的な参照することを学んだ – Gcinbax

答えて

-2

私はObject必ずしも(それは「存在」がある場合、または最寄りのタイプ)JVMは、実行時にオブジェクトタイプなどの一般的な参照のこと

を学びました。あなたのコードのような無制限のジェネリックの場合です。バインドされている場合(<T extends ParentClass>など)、ランタイムタイプはParentClassになります。あなたのコードはバインドされていないので、それはObjectになります。これはキャスト中に問題を起こさないでしょう。

今、あなたのタイプチェックを改善するために、適切なコンパイルエラーを取得するには、あなたがContainerにジェネリック型を追加する必要があります:

static class Container<T> { 
    Iterable<T> objects; 

    public Container(Iterable<T> objects) { 
     this.objects = objects; 
    } 

    public Iterable<T> getObjects() { 
     return objects; 
    } 
} 

と生Containerクラスを使用しないようにGenericを更新:

static class Generic<T> { 
    private Container<T> container; 

    public Generic(Container<T> container) { 
     this.container = container; 
    } 

    public void checkContainer() { 
     for (T key : container.getObjects()) { 
      final T genericKey = key; 
      System.out.println(genericKey); 
     } 
    } 
} 

にあなたの主な方法でdiamond operatorを追加します。

Generic<One> integerGeneric = new Generic<One>(new Container(Lists.<Object>newArrayList(new One(), new Two()))); 

そして、あなたがそれからあります:

Generic<One> integerGeneric = new Generic<>(new Container<>(Lists.newArrayList(new One(), new Two()))); 

そして、所望の種類がOneある場合Lists.newArrayList(new One(), new Two())が許可されていないことを示すコンパイラエラー。


ところで:あなたはまだジェネリック型として生タイプを使用して、またはObjectいずれかによって、このコンパイラのチェックをバイパスすることができ、両方のContainerGenericクラスはとどまるところを持っていないので、これはまだ、実行時例外が発生することはありません。

+0

誰かがdownvoteについて疑問に思う場合:[ティムBiegeleisen](https://stackoverflow.com/users/1863229/tim-biegeleisen)は、それを復讐の下降声のターゲットの1つとして使用しました。 – Tom

関連する問題