型パラメータで指定された型を引数で受け取るメソッドの定義ではまる
型パラメータで指定された型を引数で受け取るメソッドがあって、
class Test<T> { void add( T value ) {} }
このとき、「add」の引数として指定できるのは「Tと代入互換性があるクラス(T or Tの派生クラス)」になります。
で、これと同じノリで、一括登録版の「addAll」を以下のように定義してしまい困った事態に。
class Test<T> { void add( T value ) {} void addAll( List<T> value ) {} }
↑のように定義してしまうと、引数として「Tと同じ型をパラメータとして持つList」しか指定できなくなってしまい、「add」と統一のとれない仕様になってしまいます。
Test<Exception> test = new Test<Exception>(); test.add( new Exception() ); // OK test.add( new RuntimeException() ); // OK test.addAll( new ArrayList<Exception>() ); // OK //test.addAll( new ArrayList<RuntimeException>() ); // これはコンパイルエラー。
こういうときは、「List<? extends T>」を使います。これで、「TまたはTを派生した何かを要素とするList」が指定できるようになるので、「add」と同様の仕様になります。
class Test2<T> { void add( T value ) {} void addAll( List<? extends T> values ) {} }
Test2<Exception> test2 = new Test2<Exception>(); // 以下はすべてOK test2.add( new Exception() ); test2.add( new RuntimeException() ); test2.addAll( new ArrayList<Exception>() ); test2.addAll( new ArrayList<RuntimeException>() );
こんなんではまるとは。ぬう。