Зачем отмечать локальные переменные и параметры метода как "final" в Java?

В Java вы можете квалифицировать локальные переменные и параметры метода с ключевым словом final.

public static void foo(final int x) {
  final String qwerty = "bar"; 
}

Это приводит к невозможности переназначить x и qwerty в теле метода.

Эта практика подталкивает ваш код в направлении неизменности, который обычно считается плюсом. Но он также имеет тенденцию загромождать код с "окончательным" появлением повсюду. Как вы оцениваете конечное ключевое слово для локальных переменных и параметров метода в Java?

Ответ 1

Вы должны стараться делать это, когда это уместно. Кроме того, чтобы предупредить вас, когда вы "случайно" пытаетесь изменить значение, он предоставляет информацию компилятору, который может привести к лучшей оптимизации файла класса. Это один из пунктов в книге "Hardcore Java" Роберта Симмонса-младшего. Фактически, книга посвящает всю свою вторую главу об использовании финала для продвижения оптимизации и предотвращения логических ошибок. По этой причине инструменты статического анализа, такие как PMD и встроенный SA Eclipse, обозначают эти типы случаев.

Ответ 2

Мое личное мнение состоит в том, что это пустая трата времени. Я считаю, что визуальный беспорядок и добавленная многословие не стоят того.

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

Но, конечно, все личные предпочтения; -)

Ответ 3

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

Следовательно, не используя final делает ваш код менее читаемым и поддерживаемым, сам по себе:)

Конечные локальные переменные зависят от намерения и менее важны с моей точки зрения. Зависит от того, что происходит.

Ответ 4

В случае локальных переменных я стараюсь избегать этого. Это приводит к визуальному помехам и, как правило, не нужно - функция должна быть достаточно короткой или сосредоточена на одном воздействии, чтобы вы могли быстро увидеть, что вы изменяете то, что не должно быть.

В случае магических чисел я бы поставил их как постоянное частное поле в любом случае, а не в код.

Я использую только final в ситуациях, где это необходимо (например, передавая значения анонимным классам).

Ответ 5

Из-за (иногда) запутывающей природы Java "по ссылке" я определенно согласен с окончательной доработкой параметра var.

Завершение локального var кажется несколько чрезмерным IMO.

Ответ 6

Да, да.

Это о читаемости. Легче рассуждать о возможных состояниях программы, когда вы знаете, что переменные назначаются один раз и только один раз.

Достойной альтернативой является включение предупреждения IDE при назначении параметра или когда переменная (отличная от переменной цикла) назначается более одного раза.

Ответ 7

final имеет три веские причины:

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

Подобные методы, локальные переменные и параметры не обязательно должны быть объявлены окончательными. Как было сказано ранее, это загромождает код, который становится менее читаемым с очень небольшим эффектом для оптимизации производительности компилятора, это не настоящая причина для большинства фрагментов кода.

Ответ 8

Хотя он создает небольшой беспорядок, стоит положить final. Ides, например eclipse, может автоматически поместить final, если вы настроите его для этого.

Ответ 9

Создание локальных переменных и параметров метода final важно, если вы хотите передать эти параметры в анонимные классы - например, вы создаете анонимный поток и хотите получить доступ к этим параметрам в теле метода run().

Кроме того, я не уверен в преимуществах производительности w.r.t более высокой производительности благодаря оптимизации компилятора. Реализация конкретной компиляции зависит от того, хочет ли она вообще ее оптимизировать...

Хорошо знать любую статистику производительности при использовании final...

Ответ 10

Зачем вам это нужно? Вы написали метод, поэтому любой, кто его модифицировал, всегда мог удалить последнее ключевое слово из qwerty и переназначить его. Что касается сигнатуры метода, те же рассуждения, хотя я не уверен, что это будет делать с подклассами вашего класса... они могут наследовать конечный параметр и даже если они переопределяют этот метод, не смогут де-финализировать x. Попробуйте и выясните, будет ли это работать.

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

Изменить

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

Ответ 11

Я позволяю Eclipse делать это для меня, когда они используются в анонимном классе, что увеличивается благодаря использованию API Google Collection API.

Ответ 12

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

Параметры не являются окончательными, так как у нас есть Checkstyle-Check, который проверяет переназначение параметров. Конечно, никто никогда не захочет переназначить переменную параметра.