Я натрапив на код, виглядаючи приблизно так:
void run() {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() {
throw new RuntimeException();
}
Цей код мене дивує, оскільки схоже, що run()
-метод здатний кинути Exception
, оскільки він ловить, Exception
а потім перезавантажує його, але метод не оголошується кинутим 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 дозволяє 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 був більш м'яким.