Чи є якісь причини ефективності, щоб оголосити параметри методу остаточними на Java?


117

Чи є якісь причини ефективності, щоб оголосити параметри методу остаточними на Java?

А саме:

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

Проти:

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

Якщо припустимо, що barвін читається і ніколи не змінюється foo().


Я не можу придумати причину, чому компілятор би переймався, оголосив ви параметр методу остаточним чи ні. Але справжня відповідь на це питання - написати дві функції, одну з кінцевими параметрами та одну з регулярними параметрами. Запустіть їх мільйон разів кожен і подивіться, чи є помітна різниця у виконанні. Якщо ви турбуєтесь про ефективність роботи, дуже важливо виконати деяку профільну роботу над своїм кодом і з’ясувати, що саме сповільнює вас. Це майже точно не те, що ви б очікували, що це буде :)
Майк Бландфорд,

1
Я б запропонував вам ніколи не писати мікро-орієнтири. Ви не знаєте, яку оптимізацію може виконувати JIT і коли, і ви, швидше за все, отримаєте неправильне уявлення про те, як вона веде себе, просто роблячи "простий тестовий випадок"
Edmondo1984,

добре, що може бути, але ніхто тут не написав і не запропонував мікро-позначку ...
Kip

1
@ Відповідь Майка Бландфорда пропонує використовувати мікро-орієнтир, чи не так?
Бен Пейдж

Писати мікро-орієнтири на Java - це щось дуже хитро
Edmondo1984,

Відповіді:


97

Кінцеве ключове слово не відображається у файлі класу для локальних змінних та параметрів, тому воно не може вплинути на продуктивність виконання. Це лише використання для уточнення намірів кодерів, що змінна не повинна бути змінена (що багато хто вважає сумнівною причиною її використання), а також стосунки з анонімними внутрішніми класами.

Існує чимало аргументів щодо того, чи має остаточний модифікатор методу якийсь приріст продуктивності, оскільки методи будуть накреслені оптимізуючим компілятором під час виконання, незалежно від модифікатора. У цьому випадку його також слід використовувати лише для обмеження перевищення методу.


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

9
Я бачив, як компілятор Sun випромінює незначно коротший байт-код, коли єдиною різницею двох методів була "остаточність" локальних змінних. Мікрооптимізація - це справжня річ, і компілятори насправді їх роблять. Що звичайно має значення, звичайно, це те, що JIT робить з байт-кодом, а місцеві посилання втрачають свою "остаточність" при компіляції в байт-код. Я думаю, саме тому існує стільки спекуляцій щодо остаточних локальних змінних: це зовсім недетерміновані результати. Однак використання остаточних локальних пристроїв може вплинути на байт-код - на що це варто.
Крістофер Шульц

Оскільки це не детерміновано, насправді немає жодного способу залежати від оптимізації. Звичайно, багато що, можливо, змінилось у реалізаціях VM з моменту оригінальної відповіді у 2008 році ;-)
Робін

15

Єдиною перевагою остаточного параметра є те, що він може бути використаний в анонімних вкладених класах. Якщо параметр ніколи не змінюється, компілятор вже виявить, що це частина його нормальної роботи навіть без остаточного модифікатора. Досить рідко буває, що помилки викликаються несподівано призначеним параметром - якщо ваші методи досить великі, щоб потребувати цього рівня техніки, зробіть їх меншими - методи, які ви викликаєте, не можуть змінити ваші параметри.


8
"Досить рідко помилки викликані несподіваним призначенням параметра". Це частіше, ніж ти думаєш ...
RAY

2
@RAY ви можете мати рацію, адже я не маю жодних даних (крім власного досвіду), щоб підтвердити цю претензію.
Dobes Vandermeer

Якщо бути точнішим, @DobesVandermeer, це насправді не "користь для кінцевого параметра ". Те, що ви описуєте, - це просто необхідний синтаксис для будь-яких локальних змінних (серед яких я включаю параметри), щоб вони стали видимими для локальної області анонімного вкладеного класу.
swooby

0

Компілятори, які працюють після завантаження класу, наприклад компілятори JIT, можуть скористатися кінцевими методами. Отже, методи, оголошені остаточними, можуть мати певну користь.

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

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

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


10
Питання полягало в тому, що параметри оголошуються остаточними, що не впливає на продуктивність.
Робін

На сучасному фіналі JIT'S (Hotspot) фінал взагалі не має (вимірюваного) впливу на продуктивність, будь то застосований до параметрів або класу
kohlerm

2
Дві статті, які ви пов'язуєте обидві, свідчать про те, що фінал є доволі семантичним позначенням для розробників, і що компілятори JIT можуть використовувати остаточний (але, як зазначали інші, їм ця інформація дійсно не потрібна). Таким чином, остаточний є досить семантичним, який є паралельним сучасним компіляторам C / ++, здатним виводити constness змінних та методів, навіть якщо вони не позначені явно const.
ron

0

Ще один момент, що вище, ніж використання не остаточних локальних змінних, оголошених у методі, екземпляр внутрішнього класу може переживати фрейм стека, тому локальна змінна може зникнути, поки внутрішній об’єкт ще живий


-2

Я припускаю, що компілятор, можливо, може видалити всі приватні статичні кінцеві змінні, які мають примітивний тип, наприклад, int, та вбудувати їх безпосередньо в код, як і макрос C ++.

Однак у мене немає поняття, якщо це робиться на практиці, але це можна зробити для того, щоб зберегти трохи пам’яті.


Питання не в приватних остаточних змінних statc.
Маркіз Лорн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.