Does use of final keyword in Java improve the performance?
Улучшает ли производительность использование ключевого слова final в Java?
В Java мы видим множество мест, где может использоваться ключевое слово final, но его использование встречается редко.
Например:
Stringstr="abc"; System.out.println(str);
В приведенном выше случае str может быть final, но это обычно не учитывается.
Когда метод никогда не будет переопределен, мы можем использовать ключевое слово final . Аналогично в случае класса, который не будет наследоваться.
Действительно ли использование ключевого слова final в любом или во всех этих случаях повышает производительность? Если да, то каким образом? Пожалуйста, объясните. Если правильное использование final действительно имеет значение для производительности, какие привычки должен выработать Java-программист, чтобы наилучшим образом использовать ключевое слово?
Переведено автоматически
Ответ 1
Обычно нет. Для виртуальных методов HotSpot отслеживает, был ли метод фактически переопределен, и может выполнять оптимизации, такие как встраивание, исходя из предположения, что метод не был переопределен - до тех пор, пока не загрузит класс, который переопределяет метод, после чего он может отменить (или частично отменить) эти оптимизации.
(Конечно, это предполагает, что вы используете HotSpot - но это, безусловно, самая распространенная JVM, так что ...)
На мой взгляд, вы должны использовать final исходя из понятного дизайна и удобочитаемости, а не из соображений производительности. Если вы хотите что-либо изменить из соображений производительности, вам следует выполнить соответствующие измерения, прежде чем искажать наиболее четкий код - таким образом, вы сможете решить, стоит ли достигнутая дополнительная производительность ухудшения читаемости / дизайна. (По моему опыту, оно того почти никогда не стоит; YMMV.)
РЕДАКТИРОВАТЬ: Поскольку уже упоминались поля final , стоит упомянуть, что они в любом случае часто являются хорошей идеей с точки зрения четкого дизайна. Они также изменяют гарантированное поведение с точки зрения видимости между потоками: после завершения работы конструктора любые поля final гарантированно будут немедленно видны в других потоках. Это, вероятно, наиболее распространенное использование final по моему опыту, хотя, как сторонник эмпирического правила Джоша Блоха "разработай наследование или запрети его", мне, вероятно, следует использовать final чаще для классов...
Ответ 2
Краткий ответ: не беспокойтесь об этом!
Длинный ответ:
Говоря о конечных локальных переменных, имейте в виду, что использование ключевого слова final поможет компилятору статически оптимизировать код, что в конечном итоге может привести к более быстрому написанию кода. Например, конечные строки a + b в приведенном ниже примере объединяются статически (во время компиляции).
publicstaticvoidmain(String[] args) { long tStart, tElapsed;
tStart = System.currentTimeMillis(); for (inti=0; i < N_ITERATIONS; i++) testFinal(); tElapsed = System.currentTimeMillis() - tStart; System.out.println("Method with finals took " + tElapsed + " ms");
tStart = System.currentTimeMillis(); for (inti=0; i < N_ITERATIONS; i++) testNonFinal(); tElapsed = System.currentTimeMillis() - tStart; System.out.println("Method without finals took " + tElapsed + " ms");
}
}
Результат?
Method with finals took 5 ms Method without finals took 273 ms
Протестировано на виртуальной машине Java Hotspot 1.7.0_45-b18.
Итак, насколько реально улучшается производительность? Я не осмеливаюсь сказать. В большинстве случаев, вероятно, незначительно (~ 270 наносекунд в этом синтетическом тесте, потому что конкатенация строк полностью исключена - редкий случай), но в высокооптимизированном служебном коде это может быть фактором. В любом случае ответ на исходный вопрос - да, это может улучшить производительность, но в лучшем случае незначительно.
Помимо преимуществ во время компиляции, я не смог найти никаких доказательств того, что использование ключевого слова final оказывает какое-либо измеримое влияние на производительность.
Ответ 3
ДА, может. Вот пример, когда final может повысить производительность:
Conditional compilation is a technique in which lines of code are not compiled into the class file based on a particular condition. This can be used to remove tons of debugging code in a production build.
consider the following:
publicclassConditionalCompile {
privatefinalstaticboolean doSomething= false;
if (doSomething) { // do first part. }
if (doSomething) { // do second part. }
if (doSomething) { // do third part. }
if (doSomething) { // do finalization part. } }
By converting the doSomething attribute into a final attribute, you have told the compiler that whenever it sees doSomething, it should replace it with false as per the compile-time substitution rules. The first pass of the compiler changes the code to something like this:
publicclassConditionalCompile {
privatefinalstaticboolean doSomething= false;
if (false){ // do first part. }
if (false){ // do second part. }
if (false){ // do third part. }
if (false){ // do finalization part.
} }
Как только это сделано, компилятор еще раз просматривает его и видит, что в коде есть недоступные операторы. Поскольку вы работаете с высококачественным компилятором, ему не нравятся все эти недоступные байт-коды. Таким образом, оно удаляет их, и в итоге вы получаете следующее:
publicclassConditionalCompile {
privatefinalstaticboolean doSomething= false;
publicstaticvoidsomeMethodBetter( ) {
// do first part.
// do second part.
// do third part.
// do finalization part.
} }
таким образом, сокращаются любые избыточные коды или любая ненужная условная проверка.
Редактировать: В качестве примера давайте возьмем следующий код:
publicclassTest { publicstaticfinalvoidmain(String[] args) { booleanx=false; if (x) { System.out.println("x"); } finalbooleany=false; if (y) { System.out.println("y"); } if (false) { System.out.println("z"); } } }
При компиляции этого кода с помощью Java 8 и декомпиляции с помощью javap -c Test.class мы получаем:
Мы можем отметить, что скомпилированный код включает только не конечную переменную x. Это доказывает, что конечные переменные влияют на производительность, по крайней мере, в этом простом случае.
Ответ 4
Согласно IBM - это не относится к классам или методам.