あなたの知らない、メソッドに型変数を加えるべき理由〜引数を再帰的型に制限〜

ジェネリックな設計 基礎編 - プログラマーの脳みそに、メソッドをジェネリックにするべき分かりやすい条件があり、感銘を受けました。

ジェネリックメソッドでの型変数というのはこのようなメソッドに対してInとOutのデータの型の関連性を表現します。

  • 複数ある引数間で型の関連性を示す
  • 引数と戻り値の間で型の関連性を示す

ということになります。

http://d.hatena.ne.jp/Nagise/20121111/1352651148

なるほどと腑に落ちました。
しかし、ジェネリックメソッドにはまだまだ色々な可能性がある、と思い、上記に該当しないケースをいくつか探してみました。

引数を再帰的型に制限

たとえばこんなメソッドを考えてみます。
Comparableはこれ

    public static <T extends Comparable<? super T>> int compareToSelf(final T t) {
        return t.compareTo(t);
    }

t.compareTo(t) が呼べる!これは引数の型を>をみたすTに制限したからこそ。
ワイルドカードではこれは呼べません。これは2つのtに別々の捕捉変換がかかるため。*1

    public static int compareToSelf2(final Comparable<?> t) {
        // コンパイルエラー
        return t.compareTo(t);
    }

このcompareToSelfが呼べるのは再帰的な型をもつクラスのみ。
ただComparableを実装しただけのクラスではダメです。

    public static void compareToSelfTest() {
        compareToSelf(100);
        compareToSelf("hoge");
        // Comparable<Integer>継承無名クラスはIntegerのサブクラスでないのでダメ
//        compareToSelf(new Comparable<Integer>(){
//
//            @Override
//            public int compareTo(final Integer o) {
//                return 0;
//            }});
    }

引数に制約をつけるほどより強力な演算ができる。まるでHUNTER×HUNTERのようですね。
参考:制約と誓約と覚悟

つづくかも。