Почему одно из этих повторных исключений создает ошибку компилятора?
Почему throw outerE;
генерирует ошибку компиляции? Я знаю, что throw e;
не должен генерировать ошибку компилятора из-за точной функции ретролина.
Они представляют собой один и тот же объект Exception
, но один из них ограничен только внутри блока catch
, а другой - вне блока try-catch.
Не должно ли ни одна из них генерировать ошибку компилятора? Или, по крайней мере, оба ведут себя одинаково?
static void preciseRethrowTest()
{
Exception outerE;
try
{
}
catch (Exception e)
{
outerE = e;
// Compilation error here. Unhandled exception type Exception
// throw outerE;
throw e; // No compiler error
}
}
Я использую Java 1.8.0_51. (Точный ретрон введен в Java 7)
Ответы
Ответ 1
В вашем методе нет объявлений throws
.
Компилятор теперь достаточно умен, чтобы определить, что ваш блок try
не может выкинуть любые проверенные исключения. Поэтому любые исключения, обнаруженные и привязанные к параметру Exception
в вашем блоке catch
, должны быть сняты. Поскольку они не отмечены, вы можете восстановить их на досуге (и они не потребуют объявления throws
).
Здесь вы пытаетесь переназначить
outerE = e;
// Compilation error here. Unhandled exception type Exception
// throw outerE;
и перестроить исключение с помощью другой переменной. Компилятор не заходит так далеко, чтобы понять, что такое значение в outerE
. Это может быть исключение в вас пойманным или это может быть что-то другое. Компилятор играет в безопасности и не позволяет вам это делать.
Рассмотрим код типа
if (Math.random() < 0.5)
outerE = e;
else
outerE = new IOException("nope");
throw outerE;
Невозможно, чтобы компилятор знал, что значение Exception
, хранящееся в outerE
, - это неконтролируемое исключение, которое вы поймали, или какое-либо другое, потенциально проверенное исключение, которое вы назначили из другого места.
Ответ 2
Проблема заключается в том, что блоки catch не могут быть достигнуты проверенными исключениями; компилятор достаточно умен, чтобы понять это.
Рассмотрим это:
public class RethrowTest {
static void preciseRethrowTest() {
Exception outerE;
try {
throw new Exception();
} catch (Exception e) {
outerE = e;
// Compilation error here. Unhandled exception type Exception
// throw outerE;
throw e; // Now a compiler error *is* generated.
}
}
}
Это вызывает ошибку компилятора, потому что теперь код может быть достигнут проверенным исключением.