以下の様な 「例外を事前にnewしておいて使い回す」コードを書いていました。
package exceptiontest;
public class ExceptionTest {
// ここで例外を生成。
private static final RuntimeException _e = new RuntimeException("hello"); // line: 6
public static void main(String[] args) {
// 実際に投げるのはここ。
throw _e; // line: 10
}
}
結果こうなる...
Exception in thread "main" java.lang.RuntimeException: hello
at exceptiontest.ExceptionTest.<clinit>(ExceptionTest.java:6)
なんでか?
JavaはExceptionのインスタンスを生成した時点でStackTraceが決まるようです。
pythonとかだと
raise
(throw
) した時のStackTraceが出るので、同じ感覚で書いてました。
例えば、コードを以下のように書き換えても...
package exceptiontest;
public class ExceptionTest {
// ここで例外を生成。
private static final RuntimeException _e = new RuntimeException("hello"); // line: 6
private static void f1() {
f2();
}
private static void f2() {
throw _e;
}
public static void main(String[] args) {
// main() --> f1() --> f2() --> throw _e
f1();
}
}
常にExceptionをnewしている6行目のStackTraceが出ます。
Exception in thread "main" java.lang.RuntimeException: hello
at exceptiontest.ExceptionTest.<clinit>(ExceptionTest.java:6)
<clinit>
とはクラスのstatic initializerのことです。
変数_e
はクラスのstatic
要素として宣言しているので、ExceptionTest
クラスのロード時にStackTraceが決まってしまいます。
おまけ (Pythonだとこう)
期待した通りに(?)、動きます。
_e = Exception('hello')
def f1():
raise _e
if __name__ == '__main__':
f1()
Traceback (most recent call last):
File "/Users/username/Documents/workspace/raisetest/main.py", line 7, in <module>
f1()
File "/Users/username/Documents/workspace/raisetest/main.py", line 4, in f1
raise _e
Exception: hello