Почему функция multi-catch в Java требует, чтобы исключения были окончательными?

В документации Oracle по функции multi-catch, добавленной в Java 7, указано, что параметр исключения в предложении catch неявно является final.

У меня вопрос: в чем смысл такого ограничения? Потому что я не могу найти ни одного существенного улучшения, которое оно приносит. Пометка ссылочного объекта как final только защищает саму ссылку от изменения, а не объект, на который она ссылается, и никогда не запрещается создавать другую ссылку и изменять ее так, как они захотят.

Несколько актуальный вопрос о SO обсуждает причины, по которым изменение ссылки на исключение в предложении catch не является самым разумным решением, но оно касается любого использования предложения catch, а не только его множественной формы. Так почему же Java делает исключение для multi-catch и обрабатывает его особым образом?

Ответ 1

В предложении uni-catch вы можете повторно назначить объект исключения. Например, это работает отлично:

try {
    ... // code that can throw IOException or some user-defined ParserException
} catch(IOException) {
    e = new IOException();  // this is acceptable (although there is no point in doing it)
    e.printStackTrace();
}

Компилятор точно знает, что созданный объект имеет тип IOException. Однако в предложении multi catch вы можете иметь что-то вроде:

try {
    ... // code that can throw IOException or some user-defined ParserException
} catch(IOException | ParserException e) {
    e = new IOException(); // this is NOT acceptable -- e may reference a ParserException
    e.printStackTrace();
}

В этом случае компилятор понятия не имеет, какой тип исключение находится во время компиляции, поэтому присвоение нового IOException переменной, которая может ссылаться либо на ParseException IOException либо на ParseException не должно быть разрешено. К этому добавляется нехватка прецедентов для назначения переменной исключения в первую очередь. Поэтому имеет смысл сделать переменную неявно final и избежать всего этого путаницы. Если вам действительно нужно назначить переменную, вы можете перейти на старый способ записи последовательности блоков catch.

Ответ 2

Опоздал на вечеринку, но мне было интересно... Что если пункт об исключении? Это хороший способ для компилятора узнать, какое исключение обрабатывать в блоке multi-catch. Нет необходимости делать параметры multi-catch неявно окончательными. Почему дизайнеры не думают об этом? Может кто-нибудь объяснить мне? Спасибо