Generics で型に "?" を指定すると?続き
石田さんに詳しいことを調べていただいたので、それをベースにコードを組んでみました。
(石田さんありがとうございました m(_ _)m)
コードの実装例
引数の Set に格納されている要素数を返すメソッドを考えてみましょう。
private int countElements(Set<?> set) { if (set == null) { return 0; } return set.size(); }
"<?>" と定義すると、任意の型パラメータの Set を引数に取ることができます。
("<E>" ではコンパイルエラーになります。後述。)
また、"<?>" をつけると、メソッド内で Set の内容をいじれなくできます。(add() などを呼べなくなります)
(内容をいじらせなくするという効果が ( ゚д゚))
一応、引数定義を "Set set" としても、特別コンパイル時に警告も出ず、想定通りに動作します。
でもそれだと、Set
なので、"<?>" をつけておいた方がよいです。
動作確認
以下のテストコードは正常終了します。
任意の型パラメータの Set を使用できることが確認できます。
※ちなみに、"<?>" のことを、英語で "unbounded wildcard type" と言います。
public void testUnboundedWildcardType() { // ?String の Set SetstringSet = null; assertEquals( 0, countElements(stringSet)); stringSet = new TreeSet (); assertEquals( 0, countElements(stringSet)); stringSet.add("a"); assertEquals( 1, countElements(stringSet)); stringSet.add("b"); assertEquals( 2, countElements(stringSet)); // ?Integer の Set Set integerSet = null; assertEquals( 0, countElements(integerSet)); integerSet = new TreeSet (); assertEquals( 0, countElements(integerSet)); integerSet.add(1); assertEquals( 1, countElements(integerSet)); integerSet.add(2); assertEquals( 2, countElements(integerSet)); }
新たな疑問
何で countElements(Set<E> set) と定義するとコンパイルエラーになるのか?
これは明日じっくり調べてみます。