読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

型パラメータで指定された型を引数で受け取るメソッドの定義ではまる

型パラメータで指定された型を引数で受け取るメソッドがあって、

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>() );

こんなんではまるとは。ぬう。