Я наткнулся на код, который выглядит примерно так:
void run() {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() {
throw new RuntimeException();
}
Этот код удивляет меня, потому что он выглядит так, как будто run()-method способен генерировать Exception, так как он перехватывает Exceptionи затем перебрасывает его, но метод не объявлен как throw Exceptionи, очевидно, не нуждается в этом. Этот код прекрасно компилируется (по крайней мере, в Java 11).
Я ожидал бы, что мне придется объявить throws Exceptionв run()методе.
Дополнительная информация
Аналогичным образом, если doSomethingобъявлено, что оно выбрасывает, IOExceptionтогда IOExceptionнужно только объявить в run()-методе, даже если Exceptionон пойман и переброшен.
void run() throws IOException {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() throws IOException {
// ... whatever code you may want ...
}
Вопрос
Java обычно любит ясность, в чем причина такого поведения? Это всегда было так? Что в спецификации языка Java позволяетrun() методу не объявлять throws Exceptionв приведенных выше фрагментах кода? (Если я добавлю это, IntelliJ предупредит меня, что Exceptionникогда не бросается).
-source 1.6флагом вызывает ошибку компиляции, как и ожидалось. Компиляция с исходным кодом совместимости 7 никак не поднимет ошибку компиляции
In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions : 1. 1. The try block is able to throw it. 2. There are no other preceding catch blocks that can handle it. 3. It is a subtype or supertype of one of the catch clause's exception parameters.
javac- я сталкивался со случаями, когда Eclipse-компилятор был более снисходительным.