Hentikan Penugasan Kembali Variabel
Meskipun jawaban ini menarik secara intelektual, saya belum membaca jawaban singkatnya yang sederhana:
Gunakan kata kunci akhir ketika Anda ingin kompiler untuk mencegah variabel ditugaskan kembali ke objek yang berbeda.
Apakah variabel tersebut adalah variabel statis, variabel anggota, variabel lokal, atau variabel argumen / parameter, efeknya sepenuhnya sama.
Contoh
Mari kita lihat efeknya dalam aksi.
Pertimbangkan metode sederhana ini, di mana kedua variabel ( arg dan x ) keduanya dapat ditugaskan ulang objek yang berbeda.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Tandai variabel lokal sebagai final . Ini menghasilkan kesalahan kompilator.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Sebagai gantinya, mari tandai variabel parameter sebagai final . Ini juga menghasilkan kesalahan kompiler.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Pesan moral dalam cerita:
Jika Anda ingin memastikan variabel selalu menunjuk ke objek yang sama, tandai variabel final .
Jangan Tetapkan Kembali Argumen
Sebagai praktik pemrograman yang baik (dalam bahasa apa pun), Anda tidak boleh menetapkan ulang variabel parameter / argumen ke objek selain objek yang diteruskan oleh metode pemanggilan. Dalam contoh di atas, seseorang seharusnya tidak pernah menulis barisarg =
. Karena manusia membuat kesalahan, dan programmer adalah manusia, mari kita minta kompiler untuk membantu kita. Tandai setiap parameter / variabel argumen sebagai 'final' sehingga kompiler dapat menemukan dan menandai setiap penugasan ulang tersebut.
Dalam retrospeksi
Sebagaimana dicatat dalam jawaban lain ... Dengan tujuan desain asli Java untuk membantu programmer menghindari kesalahan bodoh seperti membaca melewati akhir array, Java seharusnya dirancang untuk secara otomatis menegakkan semua variabel parameter / argumen sebagai 'final'. Dengan kata lain, argumen tidak boleh berupa variabel . Namun melihat ke belakang adalah 20/20 visi, dan desainer Java memiliki tangan penuh pada saat itu.
Jadi, selalu tambahkan final
ke semua argumen?
Haruskah kita menambahkan final
setiap parameter metode yang dideklarasikan?
- Secara teori, ya.
- Dalam praktiknya, tidak.
➥ Tambahkan final
hanya ketika kode metode panjang atau rumit, di mana argumen mungkin keliru untuk variabel lokal atau anggota dan mungkin ditugaskan ulang.
Jika Anda setuju dengan praktik yang tidak pernah menetapkan ulang argumen, Anda akan cenderung untuk menambahkan argumen final
masing-masing. Tapi ini membosankan dan membuat pernyataan ini sedikit sulit dibaca.
Untuk kode pendek sederhana di mana argumen jelas merupakan argumen, dan bukan variabel lokal atau variabel anggota, saya tidak repot menambahkan final
. Jika kodenya cukup jelas, tanpa ada kemungkinan saya atau programmer lain melakukan pemeliharaan atau refactoring secara tidak sengaja salah mengartikan variabel argumen sebagai sesuatu selain argumen, maka jangan repot-repot. Dalam pekerjaan saya sendiri, saya menambahkan final
hanya dalam kode yang lebih panjang atau lebih terlibat di mana argumen mungkin keliru untuk variabel lokal atau anggota.
Kasus lain ditambahkan untuk kelengkapan
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}