Есть ли причина для повышения производительности объявлять параметры метода окончательными в Java?


117

Есть ли причина для повышения производительности объявлять параметры метода окончательными в Java?

Как в:

public void foo(int bar) { ... }

Против:

public void foo(final int bar) { ... }

Предполагая, что barэто только читается и никогда не изменяется foo().


Я не могу придумать причину, по которой компилятор будет заботиться о том, объявили ли вы параметр метода final или нет. Но настоящий ответ на этот вопрос - напишите две функции, одну с конечными параметрами, а другую с обычными параметрами. Запустите их по миллиону раз каждый и посмотрите, есть ли заметная разница во времени выполнения. Если вы беспокоитесь о производительности, очень важно провести некоторую работу по профилированию вашего кода и точно выяснить, что вас тормозит. Это почти наверняка не то, что вы ожидаете :)
Майк Бландфорд

1
Я бы посоветовал вам никогда не писать микротесты. Вы не знаете, какую оптимизацию может выполнять JIT и когда, и вы, вероятно, получите неправильное представление о том, как она себя ведет, просто выполняя «простой тестовый пример»
Edmondo1984

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

1
Ответ @Mike Blandford предлагает использовать микро-тест, не так ли?
Бен Пейдж

Написание
микротестов

Ответы:


97

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

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


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

9
Я видел, как компилятор Sun испускал немного более короткий байт-код, когда единственной разницей между этими двумя методами была «окончательность» локальных переменных. Микрооптимизации реальны, и компиляторы действительно их делают. Что действительно важно, конечно, так это то, что JIT делает с байт-кодом, а локальные ссылки теряют свою «окончательность» при компиляции в байт-код. Я думаю, что именно поэтому так много спекуляций о конечных локальных переменных: результаты не являются детерминированными. Однако использование final locals может повлиять на байт-код - чего бы он ни стоил.
Кристофер Шульц,

Поскольку он недетерминирован, на самом деле нет никакого способа зависеть от оптимизации. Конечно, многое могло измениться в реализациях виртуальной машины с момента первоначального ответа в 2008 году ;-)
Робин

15

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


8
«Очень редко ошибки вызваны неожиданным назначением параметра». Это чаще, чем вы думаете ...
РЭЙ

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

@DobesVandermeer, если быть более точным, на самом деле это не «преимущество для конечного параметра ». То, что вы описываете, является просто обязательным синтаксисом для любых локальных переменных (из которых я включаю параметры как), которые должны быть видны в локальной области анонимного вложенного класса.
swooby

0

Компиляторы, которые работают после загрузки класса, например JIT-компиляторы, могут использовать методы final. Следовательно, методы, объявленные как final, могут иметь некоторое преимущество в производительности.

http://www.javaperformancetuning.com/tips/final.shtml

О, и еще один хороший ресурс

http://mindprod.com/jgloss/final.html


10
Речь шла об объявлении параметров окончательными, что не влияет на производительность.
Робин

В современных JIT'S (Hotspot) финал вообще не имеет никакого (измеримого) влияния на производительность, независимо от того, применяется ли он к параметрам или классу
kohlerm

2
Две статьи, на которые вы ссылаетесь, предполагают, что final является скорее семантическим знаком для разработчиков и что компиляторы JIT могут использовать final (но, как указывали другие, им действительно не нужна эта информация). Таким образом, final является скорее семантическим, что соответствует способности современных компиляторов C / ++ определять постоянство переменных и методов, даже если они не отмечены как const явно.
ron

0

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


-2

Я предполагаю, что компилятор может удалить все частные статические конечные переменные с примитивным типом, например int, и встроить их непосредственно в код, как в макросе C ++.

Однако я понятия не имею, делается ли это на практике, но это можно было бы сделать для экономии памяти.


Вопрос не в частных конечных переменных statc.
Marquis of Lorne
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.