Java 7 - Точный бросок с окончательным исключением
В предыдущих версиях java, реорганизация исключения рассматривалась как бросание типа параметра catch.
Например:
public static void test() throws Exception{
DateFormat df = new SimpleDateFormat("yyyyMMdd");
try {
df.parse("x20110731");
new FileReader("file.txt").read();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
throw e;
}
}
В Java 7 вы можете уточнить об исключении, если вы объявите исключение final
:
//(doesn't compile in Java<7)
public static void test2() throws ParseException, IOException{
DateFormat df = new SimpleDateFormat("yyyyMMdd");
try {
df.parse("x20110731");
new FileReader("file.txt").read();
} catch (final Exception e) {
System.out.println("Caught exception: " + e.getMessage());
throw e;
}
}
Мой вопрос. Документы говорят, что мне нужно объявить Exception final
. Но если я этого не делаю, код выше все еще компилируется и работает. Я что-то упускаю?
Литература:
Монета проекта: многопользовательское и окончательное ретронирование
Добавить более гибкую проверку повторных исключений
Ответы
Ответ 1
Я считаю, что я видел твит из Джоша Блоха, в котором говорилось, что "последнее" ограничение было отменено поздно. Я посмотрю, смогу ли я найти сообщение об этом, но я подозреваю, что любая "ранняя" документация, которую вы читаете, теперь неточна.
EDIT: я не могу найти точную запись "она изменилась", но в документах по Java 7 показан пример, когда он не является окончательным. Он говорит о том, что переменные исключений являются неявно окончательными, когда блок catch объявляет более одного типа, но немного отличается.
EDIT: теперь я нашел источник своей путаницы, но это внутренняя почтовая рассылка:( В любом случае, это не обязательно должно быть объявлено окончательным, но я считаю, что компилятор рассматривает это как неявно окончательный - просто как в сценарии с несколькими ловушками.
Ответ 2
Причина, по которой компиляция заключается в том, что исключение в объявлении uni catch, которое впоследствии не изменяется, неявно окончательно (JLS 14.20).
Итак, для вашего примера не компилировать, вам нужно каким-то образом изменить e, например:
public static void test2() throws ParseException, IOException {
DateFormat df = new SimpleDateFormat("yyyyMMdd");
try {
df.parse("x20110731");
new FileReader("file.txt").read();
} catch (Exception e) {
if (e instanceof ParseException) {
e = new ParseException("Better message", 0);
} else {
e = new IOException("Better message");
}
System.out.println("Caught exception: " + e.getMessage());
throw e; //does not compile any more
}
}
Ответ 3
Без финала он все еще действителен java. Вы просто теряете пользу от того, чтобы быть "точным".