37

私はJavaでジェネリックを学んでいて、非常に興味深いコードに近づきました。Javaでは、あるタイプのリストを別のタイプに追加することは違法であることを知っています。

List<Integer> integerList = new ArrayList<Integer>();
List<String> stringList=integerList;

そのため、2 行目でコンパイル時エラーが発生します。
しかし、このようにクラス内にジェネリック メソッドを作成すると、

class  GenericClass <E>{
    void genericFunction(List<String> stringList) {
        stringList.add("foo");
    }
    // some other code
}

メインクラスでは、整数のリストを使用してメソッドを呼び出しますが、エラーは発生しません。

public class Main {
  public static void main(String args[]) {

     GenericClass genericClass=new GenericClass();
     List<Integer> integerList= new ArrayList<Integer>();
     integerList.add(100);
     genericClass.genericFunction(integerList);
     System.out.println(integerList.get(0));
     System.out.println(integerList.get(1));
  }
}

出力
100
foo

エラーが発生しないのはなぜですか?

4

5 に答える 5

23

GenericClass<E>生の方法で使用するため、コンパイル時エラーは発生しません:

GenericClass genericClass = new GenericClass();

気にしないので、実質的にジェネリック型チェックを無効にするようコンパイラーに指示しています。

だから:

void genericFunction(List<String> stringList)

になる

void genericFunction(List stringList)コンパイラ用。

次を試すことができます : GenericClass<?> genericClass、コンパイラがジェネリックの不適切な使用を認識し、エラーが表示されることにすぐに気付くでしょう:

The method genericFunction(List<String>) in the type GenericClass<capture#1-of ?> is not applicable for the arguments (List<Integer>)

また、実行時に 2 番目の位置オブジェクトのクラスを取得しようとすると、次のようになります。

System.out.println(integerList.get(1).getClass());

、次のエラーが表示されます java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

于 2014-08-20T09:12:35.250 に答える
19

Generic とraw typeが混在しています。正常にコンパイルされますが、実行時に汎用情報が失われるため、実行時に失敗する可能性があります。

Generic は、コンパイル時にそのようなバグを追跡するために使用する必要があります。

これは生の型とは何か、なぜそれを使用すべきではないのですか?でよりよく説明されています。詳細に。


警告:型の安全性: メソッドgenericFunction(List)は生の型に属していGenericClassます。ジェネリック型への参照GenericClass<E>はパラメーター化する必要があります。

リストのジェネリック型が異なる同じ名前の 2 つのメソッドがある場合、コンパイル時エラーが発生します。以下のサンプル コードで証明できるメソッド引数の場合、コンパイラは Generic 型を解決できません。

サンプル コード: (コンパイラ エラー - 有効なオーバーロードされたメソッドではありません)

void genericFunction(List<String> stringList){...}
void genericFunction(List<Integer> stringList){...}

いくつかの変更を加えて、もう一度試してください。

class  GenericClass <E>{
    void genericFunction(List<E> stringList) {
        ...
    }
    // some other code
}

...

GenericClass<String> genericClass=new GenericClass<String>(); // Genreric object
List<Integer> integerList= new ArrayList<Integer>();
integerList.add(100);
genericClass.genericFunction(integerList); // compile time error

このような方法でメソッドを作成します

class GenericClass<E> {
    private List<E> list = new ArrayList<E>();

    public void addAll(List<E> newList) {
        list.addAll(newList);
    }

    public void add(E e) {
        list.add(e);
    }

    public E get(int index) {
        return list.get(index);
    }
    // some other code
}
于 2014-08-20T09:13:10.873 に答える