Подтвердить что ты не робот

Java: Значение catch (final SomeException e)?

Что делает final в следующем выражении Java?

catch (final SomeExceptionType e)
4b9b3361

Ответ 1

В основном это означает:

Поймать "SomeExceptionType" в переменную "e" с обещанием, что мы не будем назначать другое исключение для "e" во время обработки исключения.

В основном это избыток, как если бы я улавливал исключение во временное имя переменной (e только допустимо для блока обработки исключений), мне не нужно так себя вести, чтобы не доверять себе, чтобы назначить другое (возможно созданное) исключение для одного и того же имени переменной.

Тем не менее, возможно, этот блок в значительной степени поддерживается группой единомышленников, и один просто хотел быть ОЧЕНЬ уверен, что e было оригинальным захваченным исключением.

---- Отредактировано в ответ на комментарий ----

Я не могу придумать по-настоящему прекрасную причину этого. Поскольку "e" не является членом (статическим или иным образом), имя "e" не будет использоваться посткомпиляцией файла класса. Другой способ заявить об этом заключается в том, что при вводе блока обработки исключений из байт-кода JVM объект не будет присваиваться ни одному из имен элементов, доступных с помощью кадра обработки JVM, он будет перенесен во внутренний стек обработки потока текущий кадр.

Даже если два потока имели доступ к одному и тому же объекту, каждый поток имел бы собственный фрейм, поэтому компилятор удалял имя "e" из внутреннего внутреннего фрейма кадра, не мог быть изменен другим потоком.

Учитывая это, единственное преимущество объявления окончательного "e" - убедиться, что будущие кодеры не случайно устанавливают "e" после входа в блок. Возможно, они предназначены для того, чтобы сделать код более надежным в многопоточной среде, но временные переменные (те, у которых есть имена, которые действительны только в блоке) не имеют последующей компиляции имен, они помещаются в стек кадров.

Вот почему

public int safe() {
  int x = 5;
  x = x + 5;
  return x;
}

обычно рассматривается как потокобезопасный, потому что он делает это (в псевдо-байт-коде)

(In the thread current frame)
push 5
push 5
add integers
return

Хотя это не безопасно для потоков

int x = 5;

public void unsafe() {
  x = 5;
  x = x + 5;
  return x;
}

потому что он делает это

(in the thread current frame)
push "this"
push 5
set member x
push "this"
get member x
push 5
add integer
set member x
get member x
return
Последний байт-код делает очевидным, что чередование двух потоков создает связь потоков с потоком, используя элемент x и посредник, в то время как первый блок кода не может иметь никакой связи между потоками, потому что нет посредника.

Ответ 2

В настоящее время это означает final почти то же самое, что и любая локальная переменная, кроме того, что она всегда "определенно назначена".

В недавних сборниках JDK7 изменение языкового проекта в проекте позволяет указать степень неявной статической типизации. Один catch может улавливать несколько различных проверенных исключений с помощью общего базового типа и реконструировать с охватывающим контекстом, только улавливая или объявляя те исключения, которые могут (статически говорящие) быть брошены в пределах try. (См. Ссылку для лучшего объяснения.)

Ответ 3

Ключевое слово final для переменных означает, что переменная может быть назначена только один раз, а поскольку здесь здесь выполняется компилятор, это означает, что переменная не может быть изменена позже в коде.

Это важное свойство, так как это означает, что он поддерживает эту конкретную переменную везде, где она используется, и нет необходимости отслеживать, где она изменяется. Это признано настолько полезным, что действие "Очистить" в Eclipse позволяет добавлять "окончательные" все, что возможно, и я считаю, что то, что вы видите, является результатом такой автоматической очистки, поскольку большинство программистов-людей будут поддерживать короткий блок catch, поэтому такое указание не требуется.

Ответ 4

Вопрос: "Что делает finally?" в других ответах на этот вопрос, и здесь, здесь, а . Но в контексте блока try-catch Спецификация Java Language Specification (JLS) §4.12.4 (выделение мое собственное):

  • Непосредственно объявлен ресурс оператора try-with-resources (§14.20.3) и параметр исключения в предложении multi-catch (§14.20) окончательным.
  • Параметр исключения в uni catch > (§14.20) может быть фактически окончательным, а не явно объявленным окончательным. Такой параметр никогда не объявляется окончательно.

В предложении с несколькими catch:

Добавление ключевого слова final в предложение multi-catch просто делает явным тот факт, что variable неявно окончательно. В общем случае всякий раз, когда ключевое слово final передает дополнительную информацию, которая помогает сделать ваш код более удобочитаемым/поддерживаемым, используйте его.

В предложении uni-catch

С другой стороны, параметр исключения в предложении uni-catch неявно завершен окончательно никогда. Таким образом, использование ключевого слова final в предложении uni-catch предотвращает выполнение следующих событий:

try {
     throw new Exception();
catch (Exception e){
    e = null;
    e.printStackTrace(); //throws a NullPointerException
}

Проблема очевидна в этом простом примере. Но два случая могут быть менее очевидными и гарантировать использование finally:

  • Если блок catch более сложный, возможно случайное переназначение. (Хотя, если блок catch сложный, вы, вероятно, ошибаетесь.)
  • Чтобы предотвратить проблемы, возникшие во время обслуживания кода. Добавление final в переменную исключения гарантирует, что переназначение будет обнаружено при компиляции, а не в Runtime

Как правило, используйте ключевое слово final в объявлении uni-catch таким же образом, как и ключевое слово final для параметра метода:

JLS§4.12.4: Объявление окончательной переменной может служить полезной документацией, что ее значение не изменится и может помочь избежать ошибок программирования.