http://www.ne.jp/asahi/hishidama/home/tech/java/generics.html http://d.hatena.ne.jp/Nagise/20101105/1288938415 !!!文法 !!例 !クラス class GenericsTest { ... } !メソッド public T test(S s, R r) { ... return T} // 呼び出し方 String s = クラス名.test("hoge", "hoge") !!用語 !型変数 型を実行時(コンパイル時)に確定するもの。 上記の例の場合、 TやS、Rをそれぞれ型変数という。 !型パラメータ 型変数のを宣言しているリスト。 上記の例の場合、 を型パラメータリストという。 !!文法上の注意 文法上混乱しやすいので注意。 ,使用箇所, 宣言, バインド, ? , 境界, & ,型変数の宣言{{br}}class test ..., ○, ×, △, ○ ,○ ,変数の型の宣言{{br}}Test test, ×, ○, ○, ○ ,× ,型変数へのバインド{{br}}new Test();, ×, ○, ×, × ,× !!!使い方 Genericsの利点は *キャストの省略 *型の保証 である。内部的には Object型(または、指定している境界の型)として処理される。 キャストは自動的に行われ、キャストの際に指定した型として扱えるかチェックされる。 コンパイル後は型の情報は失われている。これを型のイレイジャと呼ぶ。 !!型の代入互換性 GenericsではJavaの型の代入互換性ルールが通常と異なる。 public class A {} public class B extends A {} public class C extends B {} A a = new B(); B b = new C(); 上記は、可能である。が以下はエラーになる。 Hoge a = new Hoge(); // コンパイルエラー! 理由は、もしこれが可能になると以下の場合に問題が出る。 ArrayList bList = new ArrayList(); ArrayList aList = bList; // 本来は代入できないができたと仮定する aList.add(new A()); // ArrayListにはA型を代入できる B b = bList.get(0); //ArrayListなのでget()の結果はB型のはず AクラスからBクラスへのアップキャストが発生してしまう。 これに対応するためにワイルドカードでの境界指定を行う。 Hoge a = new Hoge(); !! この場合、Aクラスのサブクラスである何かであることを保証するが、型が不確定である。 そのため、 *戻り値に型変数が使われている場合、A型の返り値を保証する *引数に型変数があるメソッドを呼び出すことができなくなる(引数の型が不明であるため) !! この場合、Aクラスのスーパークラスである何かであることを保証するが、型が不確定である。 そのため、 *戻り値に型変数が使われている場合、Object型の返り値を保証する *引数に型変数があるメソッドにA型(または、A型のサブクラス)だけを渡すことを許可する {{category2 プログラミング言語,Java}}