Apakah ada alasan performa untuk mendeklarasikan parameter metode final di Java?

117

Apakah ada alasan performa untuk mendeklarasikan parameter metode final di Java?

Seperti dalam:

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

Melawan:

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

Berasumsi bahwa bar hanya dibaca dan tidak pernah diubah dalam foo().

Tidur
sumber
Saya tidak dapat memikirkan alasan mengapa compiler akan peduli jika Anda menyatakan parameter metode final atau tidak. Tetapi jawaban sebenarnya untuk pertanyaan ini adalah - tulis dua fungsi, satu dengan parameter akhir dan satu lagi dengan parameter reguler. Jalankan masing-masing jutaan kali dan lihat apakah ada perbedaan waktu proses yang nyata. Jika Anda khawatir tentang kinerja, sangat penting untuk melakukan beberapa pekerjaan profil pada kode Anda dan mencari tahu persis apa yang memperlambat Anda. Hampir pasti tidak seperti yang Anda harapkan :)
Mike Blandford
1
Saya sarankan Anda tidak pernah menulis tolok ukur mikro. Anda tidak tahu pengoptimalan mana yang dapat dilakukan JIT dan kapan, dan Anda kemungkinan besar akan mendapatkan gambaran yang salah tentang bagaimana perilakunya hanya dengan melakukan "kasus uji sederhana"
Edmondo1984
baik itu mungkin, tapi tidak ada orang di sini yang menulis atau menyarankan microbenchmark ...
Kip
1
Jawaban @ Mike Blandford menyarankan menggunakan mikro-benchmark bukan?
Ben Page
Menulis tolok ukur mikro di Java adalah sesuatu yang sangat rumit
Edmondo1984

Jawaban:

97

Kata kunci terakhir tidak muncul di file kelas untuk variabel dan parameter lokal, sehingga tidak dapat memengaruhi kinerja runtime. Ini hanya digunakan untuk memperjelas maksud pembuat kode bahwa variabel tidak diubah (yang oleh banyak orang dianggap sebagai alasan yang meragukan untuk penggunaannya), dan berurusan dengan kelas dalam anonim.

Ada banyak argumen mengenai apakah pengubah terakhir pada metode itu sendiri memiliki perolehan performa karena metode tersebut akan dimasukkan oleh compiler pengoptimalan pada waktu proses, terlepas dari pengubahnya. Dalam kasus ini, metode ini juga hanya boleh digunakan untuk membatasi penggantian metode.

Robin
sumber
5
Anda akan berpikir bahwa variabel final / params dapat dioptimalkan sebagai variabel loop ... tetapi compiler / runtime yang baik harus dapat mengetahuinya tanpa final ...
John Gardner
9
Saya telah melihat kompiler Sun memancarkan bytecode yang sedikit lebih pendek ketika satu-satunya perbedaan antara kedua metode tersebut adalah "finalitas" variabel lokal. Pengoptimalan mikro adalah hal yang nyata, dan penyusun benar-benar membuatnya. Yang benar-benar penting, tentu saja, adalah apa yang JIT lakukan dengan bytecode, dan referensi lokal kehilangan "finalitasnya" saat dikompilasi menjadi bytecode. Saya pikir inilah sebabnya ada begitu banyak spekulasi tentang variabel lokal akhir: hasilnya cukup non-deterministik. Namun, menggunakan penduduk lokal akhir dapat memengaruhi bytecode - untuk apa nilainya.
Christopher Schultz
Karena ini non deterministik, sebenarnya tidak ada cara untuk bergantung pada pengoptimalan juga. Tentu saja, banyak hal yang telah berubah dalam implementasi VM sejak jawaban asli pada tahun 2008 ;-)
Robin
15

Satu-satunya keuntungan parameter akhir adalah dapat digunakan dalam kelas bertingkat anonim. Jika sebuah parameter tidak pernah diubah, kompilator akan mendeteksi itu sebagai bagian dari operasi normalnya bahkan tanpa pengubah terakhir. Sangat jarang bahwa bug disebabkan oleh parameter yang ditetapkan secara tidak terduga - jika metode Anda cukup besar untuk memerlukan tingkat teknik ini, buat lebih kecil - metode yang Anda panggil tidak dapat mengubah parameter Anda.

Dobes Vandermeer
sumber
8
"Sangat jarang bahwa bug disebabkan oleh parameter yang ditetapkan secara tidak terduga". Ini lebih umum dari yang kamu kira ...
RAY
2
@RAY Anda mungkin benar, sebenarnya saya tidak memiliki data apa pun (di luar pengalaman saya sendiri) untuk mendukung klaim itu.
Dobes Vandermeer
@DobesVandermeer lebih tepatnya, itu sebenarnya bukan "manfaat untuk parameter akhir ". Apa yang Anda gambarkan hanyalah sintaks yang diperlukan untuk setiap variabel lokal (yang saya sertakan parameternya) agar dapat dilihat oleh lingkup lokal dari kelas bersarang anonim.
swooby
0

Kompiler yang beroperasi setelah pemuatan kelas, seperti kompiler JIT, dapat memanfaatkan metode akhir. Akibatnya, metode yang dinyatakan final dapat memiliki beberapa manfaat kinerja.

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

Oh dan sumber daya bagus lainnya

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

branchgabriel.dll
sumber
10
Pertanyaannya adalah tentang parameter yang dinyatakan final, yang tidak memiliki dampak kinerja.
Robin
Pada final JIT (Hotspot) modern tidak memiliki pengaruh kinerja (terukur) sama sekali, baik diterapkan pada parameter atau kelas
kohlerm
2
Kedua artikel yang Anda tautkan menunjukkan bahwa final lebih merupakan tanda semantik bagi pengembang, dan kompiler JIT dapat menggunakan final (tetapi seperti yang ditunjukkan orang lain, mereka tidak benar-benar membutuhkan info itu). Jadi final agak semantik, yang sejajar dengan kemampuan compiler C / ++ modern untuk menyimpulkan konstanta variabel dan metode bahkan jika mereka tidak ditandai secara eksplisit.
ron
0

Satu hal lagi di atas yang menggunakan variabel lokal non-final yang dideklarasikan dalam metode — instance kelas dalam mungkin hidup lebih lama dari frame tumpukan, sehingga variabel lokal mungkin menghilang saat objek dalam masih hidup

pengguna666
sumber
-2

Saya berasumsi kompilator mungkin bisa menghapus semua variabel final statis pribadi yang memiliki tipe primitif, seperti int, dan menyebariskannya langsung dalam kode seperti dengan makro C ++.

Namun, saya tidak tahu apakah ini dilakukan dalam praktik, tetapi itu bisa dilakukan untuk menghemat memori.

pengguna1402866
sumber
Pertanyaannya bukan tentang variabel final statc pribadi.
Marquis dari Lorne