Genericsの奥深さをちょっと覗いてみたよ

元ネタはこちら。→Google グループ
#って,読めません。:-P

public class RethrowDemo {
    public static void main(String[] args) {
        RethrowDemo demo = new RethrowDemo();
        try {
            demo.someMethod();
        } catch (Exception t) {
            System.out.println("t.getClass() = " + t.getClass());  // (1)
            t.printStackTrace(System.out);
        }
    }

    void someMethod() {
        try {
            throwSomeException();
        } catch (Throwable t) {
            rethrowAny(t);
        }
    }

    void throwSomeException() throws InterruptedException {
        throw new InterruptedException();
    }

    static void rethrowAny(Throwable t) {
        RethrowDemo.<RuntimeException>rethrowInternal(t);
    }

    @SuppressWarnings("unchecked")
    static <T extends Throwable> void rethrowInternal(Throwable t) throws T {
        throw (T) t;
    }
}

なんで (1) に検査例外の 'InterruptedException' が飛んでくるのか,だれか教えてくれ。rethrowInternal()のパラメタ化がタネだと思うんだけど,なんで「throw (T) t;」が成立すんの?


(追記)るいもさんところで解説がありました。実に便利な世の中だ。

チェック例外への対処はコンパイル時に行われるから、Genericsを使って「これはRuntimeExceptionだからね〜」とだまして、 InterruptedExceptionを渡す。throw (T) t;のキャストは、所詮はイレージャだから、コンパイル時のチェックのみで、実行時には消えてなくなってしまい、別にcheckcastされるわけではない。

トップ

なるほどー。検査例外のガードってコンパイラのお仕事だから,そこをだまくらかせば通っちゃうのかー。せめてもの礼儀として「@SuppressWarnings("unchecked")」を付けといたけど,意外に大事な表明かもね。