大体その認識でいいと思います。
注意すべきは、Pocket<String>
とPocket<Integer>
は実体としては全く同じであるということです。
例のPocketは、コンパイルして生成されると、型引数として使われているEがすべてObjectで置き換えられたclassファイルが生成されます。それをコンパイラは、ジェネリクスに応じた型にキャストしたり、引数として妥当な型か判断したりします。
java
1Pocket<String> p = new Pocket<>();
2p.put("abc");
3String a = p.get();
このようなコードを書いたとすると、実際に行われるのはこうです。
java
1Pocket<String> p = new Pocket<>();
2p.put("abc"); // "abc"という文字列が"Object型の変数"のdataに収められる
3String a = (String)p.get(); // "Object型の変数"に収められた"abc"を、Stringにキャストして返す
このため、ワイルドカードや未加工型を使うことによって次のような操作が可能になりますが
java
1// ワイルドカード"?"は、そのジェネリクスがなんでもよいというもの。
2Pocket<?> p1 = new Pocket<String>();
3// Pocket<String>もPocket<Integer>も、実際の型としては全く同じであるため、このような代入が可能
4// ただし、eclipseなどでは「未検査キャスト」などの警告(コンパイルエラーではない)が出る
5Pocket<Integer> p2 = (Pocket<Integer>)p1;
異なる型のものを入れたものをこのようなキャストで入れた場合、取り出そうとするとClassCastExceptionが発生します。
java
1Pocket<String> p0 = new Pocket<String>();
2p0.put("abc");
3Pocket<?> p1 = p0;
4Pocket<Integer> p2 = (Pocket<Integer>)p1;
5Integer i = p2.get(); // "abc"をIntegerにキャストしようとしてClassCastException発生
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。