Java позволяет помечать переменные (поля / локальные объекты / параметры) как final
, чтобы предотвратить переназначение в них. Я нахожу это очень полезным с полями, так как это помогает мне быстро увидеть, являются ли некоторые атрибуты - или целый класс - неизменяемыми.
С другой стороны, я считаю, что это гораздо менее полезно с локальными параметрами и параметрами, и обычно я избегаю помечать их так, как final
будто они никогда не будут переназначены (за исключением тех случаев, когда их нужно использовать во внутреннем классе). , В последнее время, однако, я наткнулся на код, который использовал final, когда это возможно, что, я думаю, технически предоставляет больше информации.
Я больше не уверен в своем стиле программирования. Интересно, какие еще преимущества и недостатки применяются в final
любом месте, каков наиболее распространенный отраслевой стиль и почему.
final
или нет, и оптимизировали соответствующим образом. Современные компиляторы достаточно умны, чтобы понять это для себя. По крайней мере, на локальные переменные,final
строго в интересах читателей. Если ваши рутины не слишком сложны, то большинство читателей-людей должны быть в состоянии понять это и для себя.Ответы:
Я использую так
final
же, как вы. Для меня это выглядит излишним по локальным переменным и параметрам метода и не дает полезной дополнительной информации.Одна важная вещь заключается в том, чтобы мои методы были короткими и чистыми , каждый из которых выполнял одну задачу. Таким образом, мои локальные переменные и параметры имеют очень ограниченную область применения и используются только для одной цели. Это сводит к минимуму вероятность непреднамеренного переназначения их.
Более того, как вы наверняка знаете,
final
не гарантирует, что вы не можете изменить значение / состояние (не примитивной) переменной. Только то, что вы не можете переназначить ссылку на этот объект после инициализации. Другими словами, он работает без проблем только с переменными примитивных или неизменных типов. Рассмотреть возможностьЭто означает, что во многих случаях это все еще не облегчает понимание того, что происходит внутри кода, и неправильное понимание этого может на самом деле вызывать скрытые ошибки, которые трудно обнаружить.
источник
final
, спасибо :), но хорошее замечание о методах short и clean - я думаю, что если метод достаточно короткий, то очевидно, что переменная не переопределяется, есть еще менее мотив для рассмотренияfinal
ключевого слова.Ваш стиль программирования Java и ваши мысли в порядке - не нужно сомневаться в этом.
Именно поэтому вы должны использовать
final
ключевое слово. Вы заявляете, что ВЫ знаете, что он никогда не будет переназначен, но никто больше этого не знает. Использованиеfinal
немедленно устраняет неоднозначность вашего кода.источник
final
заявляет намерение, что делает код более читабельным. Кроме того, как только вы столкнетесь с реальным кодом, вы заметите, что он редко бывает нетронутым и ясным, а свободное добавлениеfinal
s везде, где вы можете, поможет вам обнаружить ошибки и лучше понять унаследованный код.final
заявляет намерение, что обычно является хорошей вещью в куске кода, но оно достигается ценой добавления визуального беспорядка. Как и большинство вещей в программировании, здесь есть компромисс: выражает ли тот факт, что ваша переменная будет использоваться только один раз, если она будет стоить дополнительной детализации?final
. Это может быть большинство местных жителей, но явно не все . Для меня не бывает "никогда не изменится". В моем мире есть 2 четко разделенных вида местных жителей. Те, которые никогда не должны меняться снова (окончательно), и те, которые должны измениться в результате того, что диктует задача (которых очень мало, что делает функции довольно легко рассуждать).Одним из преимуществ использования
final
/const
везде, где это возможно, является то, что это уменьшает умственную нагрузку для читателя вашего кода.Он может быть уверен, что значение / ссылка никогда не изменится в дальнейшем. Поэтому ему не нужно обращать внимание на модификации, чтобы понять вычисления.
Я изменил свое мнение об этом после изучения чисто функциональных языков программирования. Мальчик, какое облегчение, если вы можете доверять «переменной», чтобы всегда держать ее начальное значение.
источник
final
не гарантируется, что вы не можете изменить значение / состояние (не примитивной) переменной. Только то, что вы не можете переназначить ссылку на этот объект после инициализации.final
В параметрах метода и локальных переменных я считаю шум кода. Объявления методов Java могут быть довольно длинными (особенно с обобщениями) - больше нет необходимости их делать.Если модульные тесты написаны правильно, присваивая параметры , что является «вредным» будет подобрано, поэтому он никогда не должен фактически быть проблемой. Визуальная ясность важнее, чем избегать возможной ошибки, которая не обнаружена , потому что ваши юнит-тесты имеют недостаточный охват.
Такие инструменты, как FindBugs и CheckStyle, которые можно настроить для разрыва сборки, если присваиваются параметры или локальные переменные, если вы серьезно заботитесь о таких вещах
Конечно, если вам нужно сделать их окончательными, например, потому что вы используете значение в анонимном классе, то нет проблем - это самое простое и чистое решение.
Помимо очевидного эффекта добавления дополнительных ключевых слов к вашим параметрам и, тем самым, ИМХО их маскировки, добавление окончательных параметров метода часто может сделать код в теле метода менее читабельным, что делает код хуже - «хорошим» кодом. должно быть максимально читабельным и максимально простым. Для надуманного примера, скажем, у меня есть метод, который должен работать без учета регистра.
Без
final
:Просто. Clean. Все знают, что происходит.
Теперь с «окончательным», вариант 1:
Хотя создание параметров
final
не позволяет кодеру добавлять код дальше от мысли о том, что он работает с исходным значением, существует равный риск того, что код, который находится ниже, может использоватьinput
вместо тогоlowercaseInput
, чего он не должен и который не может защитить, потому что вы можете ' т вывести его из сферы (или даже назначитьnull
наinput
если бы даже помочь в любом случае).С 'final', вариант 2:
Теперь мы просто создали еще больше шума в коде и представили снижение производительности из-за необходимости вызывать
toLowerCase()
n раз.С 'final', вариант 3:
Поговорим о кодовом шуме. Это крушение поезда. У нас есть новый метод, обязательный блок исключений, потому что другой код может вызвать его неправильно. Дополнительные юнит-тесты для исключения. Все, чтобы избежать одной простой и ИМХО предпочтительной и безвредной линии.
Также существует проблема, заключающаяся в том, что методы не должны быть такими длинными, чтобы вы не могли легко визуально воспринять их и сразу увидеть, что имело место присвоение параметра.
Я действительно считаю хорошей практикой / стилем, что если вы назначаете параметр, вы делаете это каждый в начале метода, предпочтительно в первой строке или сразу после базовой проверки ввода, эффективно заменяя его для всего метода, что оказывает последовательный эффект в пределах метод. Читатели знают, что любое назначение должно быть очевидным (рядом с объявлением подписи) и в согласованном месте, что значительно смягчает проблему, которую пытается избежать добавление final. На самом деле я редко назначаю параметры, но если я это делаю, я всегда делаю это в начале метода.
Обратите внимание, что
final
это не защищает вас так, как это может показаться на первый взгляд:final
не защищает вас полностью, если тип параметра не является примитивным или неизменным.источник
final
дает частичную гарантию того, что вы имеете дело с одним и тем жеDate
экземпляром. Некоторые гарантии лучше, чем ничего (во всяком случае, вы спорите о неизменных классах с нуля!). В любом случае, на практике многое из того, что вы говорите, должно влиять на существующие языки по умолчанию, но это не так, что означает, что это не проблема.final
, с возможностью сделать их не окончательными для случаев, подобных выше. Просто не стоит спамить подпись ключевым словом.input
вместоlowercaseInput
тоо. Несмотря на техническую корректность, легко обнаружить ошибку, если она вызывает ошибку, так как вы можете четко видеть различную семантику двух отдельно названных переменных в месте их использования (при условии, что вы дадите им хорошие имена). Для меня более опасно объединять два семантически разных использования отдельных значений в одну и ту же переменную и, следовательно, в одно и то же имя. Это может усложнить отслеживание ошибок, так как вам придется читать и понимать весь предыдущий код, так или иначе связанный с переменной 1.Я ставлю eclipse
final
перед каждой локальной переменной, так как считаю, что программа легче читается. Я не делаю это с параметрами, так как хочу, чтобы список параметров был как можно более коротким, в идеале он должен умещаться в одну строку.источник
var
для маркировки не финальных переменных. YMMV.var
! К сожалению, в Java это не по умолчанию, и теперь уже слишком поздно менять язык. Поэтому я готов мириться с незначительными неудобствами при написанииfinal
:)final
добавленное ключевое слово, в то время как только 10-20% потребуетсяvar
...