読者です 読者をやめる 読者になる 読者になる

境界ワイルドカード型の指定方法が覚えられない

Javaジェネリックスで境界ワイルドカード型のパラメータを使用するときに、<? extends T> と <? super T> どちらを指定すればいいか迷っていた時期がありました。
今日はなぜか TL でジェネリックスの話題が多く *1 、当時のことを思い出したので懐古エントリを書いてみます。

PECS イディオム

Java で境界ワイルドカード型のパラメータを使用するときのイディオムは良く知られていて、Effective Java では以下のように述べられています。

どちらのワイルドカード型を使用すべきかを覚えるための略語は、次の通りです。

PECS は、プロデューサー (producer) -extends、コンシューマー (consumer) -super を表わしています。

プロデューサーの場合には <? extends T>、コンシューマーの場合には <? super T> を指定する、簡単です…なのですが、実際に使う段になると慣れないうちは「あれ? これは PECS の P と C どっちになるのかな?」といったことがありました。

Collections.copy

そんな時にふと見た Collections.copy のメソッドシグニチャー。
これがすごく分かりやすい。

パラメータ dest がコンシューマー (消費者)、src が プロデューサー (生産者) というのが一目瞭然です。
そう思わなくても境界ワイルドカード型の適用の仕方がまんま書いてあります。

public static <T> void copy(List<? super T> dest, List<? extends T> src) {

こういうのに頼るのはあまり良くないかもしれませんが、おかげで今では PECS を自然に扱えるようになりました。
ジェネリックス、まだまだ使いこなせていませんが便利ですねぇ。 *2

Effective Java 第2版 (The Java Series)

Effective Java 第2版 (The Java Series)

*1:JJUG でした

*2:ジェネリックス禁止な職場があると聞いたこともありますが、なぜ禁止するのか理由が分かりません…