1

私はこのデモを持っています。これは、再描画されたアーキテクチャを備えた特定のソリューションを必要としませんが、なぜそのように動作するのか、それを回避するために欠けているものを理解するだけです。なぜだろうと思っています:

  • コンパイラは、リストのタイプではない要素をリストに挿入できます
  • 要素をプッシュするときではなく、要素を取得しようとすると ClassCast 例外がスローされます

    import Test.*; //Inner classes
    import java.util.List;
    import java.util.ArrayList;
    
    public class Test<E extends Object> {
    
        private List<E> list = new ArrayList<E>();
        public Test() {}
    
        public static void main(String[] args) {
            Test<String> a = new Test<String>();
            a.addElement(new String());
            a.addElement(new Integer(0)); // No complain in comp/run-time, I dont understand why CastException is not thrown here
            String class1 = a.getElement(0); 
            String class2 = a.getElement(1); //No complain in comp but ClassCastException: Integer cannot be cast to String
            //Integer class3 = a.getElement(1); //Compilation error
        }
    
        public void addElement (Object node) { list.add((E) node); } //No complain in comp/run-time
        public E getElement(int index)       { return list.get(index); }
    }
    

What could be a solution? Notice the line addElement where I need to pass a SuperClass, instead of type E. This is needed for my architecture, this is just a simple mock demo. But anyway the casting to type E should act as desired and throw a CastExeption in runtime, should not?

4

2 に答える 2

5

addElement メソッドは、コンパイル時のエラーをキャッチできるようにジェネリックを適切に使用していません。そのはず:

public void addElement(E node) {
  list.add(node);
}

Object キャストを使用して E にキャストすると、コンパイル時の型チェックの利点が失われます。そのため、オブジェクト変数の使用を避け、キャストを避けるために、最初にジェネリックを使用します。

実行時には、ジェネリック型の消去により、リストは単にオブジェクトのリストであるため、オブジェクトをリストに配置するときの最初のキャストは発生しないことに注意してください。ただし、リストからアイテムを抽出し、それを具象型変数に割り当てる必要がある場合、舞台裏でキャストが発生し、これにより例外がスローされます。

于 2012-07-21T18:33:42.330 に答える
4

問題は(E) node、型消去のために実行時の型チェックを行わないことです。ジェネリック型に関するすべての情報は、コンパイル後に失われます。

Javaコンパイラはそれについて警告するはずです:

Type safety: Unchecked cast from Object to E

このチェックは、java.lang.Classへの参照を使用して手動で行うことができます。

private Class<E> clazz;

public Test(Class clazz) {
    this.clazz = clazz;
}

public void addElement (Object node) {
    list.add(clazz.cast(node));
}

public static void main(String[] args) {
    Test<String> test = new Test(String.class);
    test.addElement("test");
    test.addElement(Integer.intValue(10));
}
于 2012-07-21T18:50:18.637 に答える