Ответ 1
Это зависит от вашего определения "безопасный". Исключение даст ложную трассировку стека, которую я бы не назвал "безопасным". Рассмотрим:
public class ThrowTest {
private static Exception e = new Exception("t1"); // Line 2
public static final void main(String[] args) {
ThrowTest tt;
tt = new ThrowTest();
try {
tt.t1();
}
catch (Exception ex) {
System.out.println("t1:");
ex.printStackTrace(System.out);
}
try {
tt.t2(); // Line 16
}
catch (Exception ex) {
System.out.println("t2:");
ex.printStackTrace(System.out);
}
}
private void t1()
throws Exception {
throw this.e;
}
private void t2()
throws Exception {
throw new Exception("t2"); // Line 31
}
}
У этого вывода есть:
$ java ThrowTest t1: java.lang.Exception: t1 at ThrowTest.<clinit>(ThrowTest.java:2) t2: java.lang.Exception: t2 at ThrowTest.t2(ThrowTest.java:31) at ThrowTest.main(ThrowTest.java:16)
Обратите внимание, как метод t1
полностью отсутствует в трассировке стека в первом тестовом случае. Нет никакой полезной контекстной информации вообще.
Теперь вы можете использовать fillInStackTrace
для заполнения этой информации непосредственно перед броском:
this.e.fillInStackTrace();
throw this.e;
... но это просто делает работу для себя (работа, которую вы иногда забудете). Просто нет никакой пользы от этого вообще. И не все исключения позволяют это сделать (некоторые исключения делают трассировку стека только для чтения).
Вы сказали в других комментариях, что это нужно избегать "дублирования кода". У вас много улучшена функция создания исключения:
private IllegalStateException buildISE() {
return new IllegalStateException("le sophisticated way");
}
(Может быть static final
, если хотите.)
И затем брось так:
throw buildISE();
Это позволяет избежать дублирования кода без ошибочных стеков стека и ненужных экземпляров Exception.
Вот что это похоже на приведенное выше:
public class ThrowTest {
public static final void main(String[] args) {
ThrowTest tt;
tt = new ThrowTest();
try {
tt.t1(); // Line 8
}
catch (Exception ex) {
System.out.println("t1:");
ex.printStackTrace(System.out);
}
try {
tt.t2(); // Line 15
}
catch (Exception ex) {
System.out.println("t2:");
ex.printStackTrace(System.out);
}
}
private static final Exception buildEx() {
return new Exception("t1"); // Line 24
}
private void t1()
throws Exception {
throw buildEx(); // Line 29
}
private void t2()
throws Exception {
throw new Exception("t2"); // Line 34
}
}
$ java ThrowTest t1: java.lang.Exception: t1 at ThrowTest.buildEx(ThrowTest.java:24) at ThrowTest.t1(ThrowTest.java:29) at ThrowTest.main(ThrowTest.java:8) t2: java.lang.Exception: t2 at ThrowTest.t2(ThrowTest.java:34) at ThrowTest.main(ThrowTest.java:15)