ジェネリックコンストラクタの使いどころ

メソッドと同じく、コントストラクタをジェネリックにする(型パラメータをとる)ことができる。
ところがコンストラクタの型パラメータの使い途がよく分からない。

参考:
コンストラクタジェネリック - カタヤマンがプログラマチックに今日もコードアシスト
Enumのコンストラクタのローカルなジェネリクス型パラメータの怪

そこで使い途を考えた。

package test;


public class GenericConstructorTest {

    // インスタンスで必要なのはRunnable
    private Runnable runnable;
    
    // コンストラクタ 上限境界にCloneable
    public <T extends Runnable & Cloneable> GenericConstructorTest(
            final T runnable) {
        try {
            // リフレクションでclone()
            this.runnable = (Runnable) runnable.getClass().getMethod("clone")
                    .invoke(runnable);
        } catch (Exception e) {
            throw new IllegalArgumentException("need public clone()", e);
        }
    }
    
    public void start() {
        new Thread(this.runnable).start();
    }
    
    // Runnable かつ Cloneable
    static class CloneableRunnable implements Runnable, Cloneable {

        @Override
        public void run() {
            System.out.println("hoge");
        }

        @Override
        public Object clone() {
            try {
                return super.clone();
            } catch (CloneNotSupportedException e) {
                throw new AssertionError("unexpected exception", e);
            }
        }
        
    }
    
    // Runnableのみ
    static class OnlyRunnable implements Runnable {

        @Override
        public void run() {
            System.out.println("fuga");
        }
        
    }
    
    public static void main(final String[] args) {
        new <CloneableRunnable> GenericConstructorTest(new CloneableRunnable())
                .start();
        // コンパイルエラー
//        new <OnlyRunnable> GenericConstructorTest(new OnlyRunnable()).start();
    }

}

コンストラクタに渡される引数runnableは、インスタンスが生成された後はRunnableでありさえすればいいが、
コンストラクタ内(インスタンスの初期化時)ではさらにCloneableでもあってほしい。
このような場合に、 と宣言することで上限境界を追加する。
これでrunnableがCloneableであることがコンパイル時にチェックできる。

この場合リフレクションでclone()を読んでいるので、あまりインターフェースのありがたみがないが…

まとめ

初期化時にしか必要ない上限境界インターフェースを(複数)指定するのに使える。

関連?

(2013/01/14追記)コンストラクタはメソッドの一種と考えれば、メソッドをジェネリックにする理由と同じと考えられる。
メソッドをジェネリックにする動機についてはあなたの知らない、メソッドに型変数を加えるべき理由〜引数を再帰的型に制限〜などで議論する。