私は最近、javac コンパイラーを介してチェック済み例外をこっそりとスローして、スローしてはならない場所にスローすることが可能であるという事実を発見し、ブログに書きました。これは Java 6 および 7 でコンパイルおよび実行され、with or 句がスローさSQLException
れthrows
ますcatch
。
public class Test {
// No throws clause here
public static void main(String[] args) {
doThrow(new SQLException());
}
static void doThrow(Exception e) {
Test.<RuntimeException> doThrow0(e);
}
static <E extends Exception> void doThrow0(Exception e) throws E {
throw (E) e;
}
}
生成されたバイトコードは、JVM がチェック済み/未チェックの例外をあまり気にしていないことを示しています。
// Method descriptor #22 (Ljava/lang/Exception;)V
// Stack: 1, Locals: 1
static void doThrow(java.lang.Exception e);
0 aload_0 [e]
1 invokestatic Test.doThrow0(java.lang.Exception) : void [25]
4 return
Line numbers:
[pc: 0, line: 11]
[pc: 4, line: 12]
Local variable table:
[pc: 0, pc: 5] local: e index: 0 type: java.lang.Exception
// Method descriptor #22 (Ljava/lang/Exception;)V
// Signature: <E:Ljava/lang/Exception;>(Ljava/lang/Exception;)V^TE;
// Stack: 1, Locals: 1
static void doThrow0(java.lang.Exception e) throws java.lang.Exception;
0 aload_0 [e]
1 athrow
Line numbers:
[pc: 0, line: 16]
Local variable table:
[pc: 0, pc: 2] local: e index: 0 type: java.lang.Exception
これを受け入れるJVMは1つのことです。しかし、Java-the-languageがそうあるべきかどうか、私には疑問があります。JLS のどの部分がこの動作を正当化しますか? バグですか?それとも、Java 言語の隠れた「機能」ですか?
私の気持ちは次のとおりです。
doThrow0()
はin に<E>
バインドされています。したがって、JLS §11.2の行に沿った節は では必要ありません。RuntimeException
doThrow()
throws
doThrow()
RuntimeException
は との代入互換性があるため、コンパイラによってException
キャスト (結果として) が生成されません。ClassCastException