2015-05-28 6 views
8

Теперь я недавно натолкнулся на рекомендацию, чтобы вы максимально использовали ключевое слово final. Это хорошо, чтобы программист не стрелял в свою ногу, то есть переназначить переменную, которую нельзя переназначать.Имеет ли ключевое слово final какое-либо влияние на JVM?

Но может ли он служить любой другой цели? То есть, может ли JVM использовать информацию о конечных переменных, чтобы как-то оптимизировать байт-код, поэтому он будет работать быстрее (постройте лучшую конвейерную обработку или используйте ее в многопоточной среде)? Или это просто синтаксический сахар, который минимизирует вероятность ошибок при разработке кода?

+0

final или вы можете указать постоянную помощь в Оптимизациях компилятора. например: - Постоянное сгибание, Постоянное распространение –

+0

Связано: http://stackoverflow.com/questions/3961881/why-defining-class-as-final-improves-jvm-performance?rq=1 – Patrick

+0

«Или это просто синтаксический сахар что минимизирует вероятность ошибок при разработке кода? " Фактическое умное мышление сводит к минимуму ошибки. Без этого последнее ключевое слово - это не только синтаксический сахар, но и плацебо. – Gimby

ответ

4

IBM states:

Как и многие другие мифы о производительности Java, ошибочное представление о том, что объявляя классы или методы, окончательные результаты в более высокой производительности является широко распространенным, но редко рассмотренного. Аргумент гласит, что объявление метода или класса как окончательного означает, что компилятор может встроить метод вызова более агрессивно, потому что он знает, что во время выполнения это определенно версия метода, который будет вызываться. Но это просто неправда.Просто потому, что класс X скомпилирован против конечного класса Y, это не означает, что во время выполнения будет загружена одна и та же версия класса Y. Таким образом, компилятор не может встроить такие методы межсетевого метода безопасно, окончательно или нет. Только в том случае, если метод является приватным, компилятор может свободно подключать его, и в этом случае последнее ключевое слово будет избыточным.

4

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

Методы - это немного другая история: когда вы отмечаете метод final, Java может быстрее вызвать такой метод, потому что ему больше не нужно проверять его переопределения. Тем не менее, «горячая точка» достаточно умен, чтобы понять, что нет переопределений, с использованием или без использования final.

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

+0

Что относительно частных методов? Нужно ли им последнее ключевое слово? В конце концов, они определенно не могут быть переопределены. –

+0

@ SPIRiT_1984 'private' методы не обязательно должны быть отмечены' final' - они получают выгоду от той же оптимизации, что и конечные методы (методы 'static' тоже получают это, потому что они не могут быть переопределены в Java). – dasblinkenlight

+0

«Java» (hotspot действительно), как правило, достаточно умный, чтобы выяснить, никогда ли метод не перезаписывается, и делает ли эти оптимизации так или иначе, так что да, последний абзац. – Voo

1

окончательные методы могут или не могут быть объединены JVM до тех пор, пока они не будут загружены JVM. Итак, если вы уверены, что метод не будет переопределен, отметьте его как final.

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

+0

_если вы уверены, что метод не будет переопределен, отметьте его как final._ Я бы никогда не был уверен в этом, если бы не знал, почему метод _must_ не переопределяется (например, если он вызывается из конструктор). Просто потому, что я не могу думать о причине переопределения метода, не означает, что какой-то другой программист не будет думать о причине. –

+0

@ james-large, как правило, когда вы создаете библиотеку и хотите контролировать, какие классы и методы «разрешены» для переопределения, конечное ключевое слово просто дает вам механизм для этого. Это то, что я имел в виду под моим заявлением. – Farhad

+1

Правильно, и я бы никогда не захотел контролировать это, если бы не знал о специальном случае, когда переопределение клиента может помешать одному из классов _my_ вести себя так, как я обещал, что он будет себя вести. –

1

Я думаю, что эта рекомендация слишком неспецифична.

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

Я также обнаружил, что использование final для параметров метода - всего лишь пустая трата «пространства экрана» (и тем самым: трата «энергии» на стороне читателя).

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

Как вы видите; есть много плюсов и минусов относительно использования финала; и я думаю, что «читаемость» чаще всего выигрывает над «потенциальными» улучшениями производительности.