1

ジェネリックを使用することで、コンパイル中に可能性を検出します。例えば、

List<String> list = new ArrayList<String>();
//list.add(new Integer(45)); This will cause compilation error.
list.add("car");
list.add("bus");
list.add("bike");
String vehicle = list.get(0); //compiler-generated cast

Java 1.5 より前のジェネリックの代わりに生の型を使用する場合は、明示的なキャストが必要です。例えば、

List list2 = new ArrayList();
    list.add("car");
    list.add("bus");
    list.add("bike");
    String vehicle = (String)list.get(0); //explicit casting is necessary

ただし、ジェネリックでは、型の消去が発生します。つまり、実行時に型情報が失われます。そうである場合、JVM は実行時に取得するオブジェクトの種類を、それが文字列オブジェクトであるか人物オブジェクトであるか (上記のコンパイラで生成されたキャスト) にどのように認識しますか。ただし、これはジェネリックで有効であり、実行時エラーを引き起こす可能性があります。

List<Object> test = new ArrayList<Object>();
            test.add("hello");
            test.add(new Integer(34));

最後に、Joshua Bloch が 115 ページ (item 23、有効な Java) で言及している Set<Object>のは、任意の型のオブジェクトを含むことができるセットを表すパラメーター化された型で Set<?>あり、未知の型のオブジェクトのみを含むことができるセットを表すワイルドカード型でSetあり、ジェネリック型システムをオプトアウトする raw 型。

彼の上記の発言の意味は理解できます。いくつかの説明が役立ちます

4

4 に答える 4

5

コンパイラは、ジェネリック メソッドから項目を取得するときにキャスト操作を挿入します。これは、JVM が の結果をlist.get(0)として扱うことを認識している唯一の方法ですString。これが、ヒープ汚染 (間違ったタイプのオブジェクトをジェネリック コレクションに挿入すること) がClassCastException実行時に発生する可能性がある理由です。

ワイルドカードについて:

  • Set<Object>のジェネリック型は正確にObjectです。そこからインスタンスを挿入および取得することはできますが、メソッドが非オブジェクトをセットに追加することを計画している可能性があるため、を期待するメソッドに a をObject渡すことはできません。Set<Integer>Set<Object>Integer
  • Set<?>指定されていないジェネリック型があります。Objectメソッドは(すべてが であるため) から何でも取得でき、またはのObjectようなユニバーサル メソッドを呼び出すことができますが、セットに何も追加することはできません。hashCodetoString
  • Set、あなたが言及したように、生の型であり、新しいコードでは使用しないでください。
于 2013-09-04T03:50:15.913 に答える
1

よくわかりませんが、実行時にタイプ情報が失われることを理解しているのは、実行時にコレクションが特定のタイプであるという方法がないということです。コレクションにa を追加するStringと、それは aStringのみになりますが、コレクションはすべての要素が型でなければならないことを強制しませんString

于 2013-09-04T03:54:58.410 に答える
0

ジェネリックは、Java コンパイラによって、消去と呼ばれるフロントエンド変換として実装されます。型消去は、ジェネリックの使用に適用されます。ジェネリックを使用すると、コンパイル時のチェックと実行時の型キャストに変換されます。

型消去メカニズムにより、このコード:

List<String> a = new ArrayList<String>();
a.add("foo");
String x = a.get(0);

これにコンパイルされます:

List a = new ArrayList();
a.add("foo");
String x = (String) a.get(0);

型の消去後に、コンパイル済みのコンパイル済みコードに余分なキャストが挿入されていることに注意してください。

PS: @chrylis は、質問の 2 番目の部分について既に適切な説明を提供しています。

于 2013-09-04T04:07:09.933 に答える
0

さて、このスタックオーバーフローの質問はあなたを助けることができます.

Eclipse はこのメソッドを使用して、クラス内のフィールドとそのジェネリック型 (存在する場合) を検出している可能性があります。ご覧ください。

于 2013-09-04T04:16:14.127 に答える