it-swarm-id.com

Di Jawa, haruskah saya menggunakan "final" untuk parameter dan penduduk lokal meskipun saya tidak harus melakukannya?

Java memungkinkan penandaan variabel (bidang/lokal/parameter) sebagai final, untuk mencegah penugasan kembali ke dalamnya. Saya merasa sangat berguna dengan bidang, karena membantu saya dengan cepat melihat apakah beberapa atribut - atau seluruh kelas - dimaksudkan untuk tidak berubah.

Di sisi lain, saya merasa itu jauh kurang berguna dengan penduduk lokal dan parameter, dan biasanya saya menghindari menandai mereka sebagai final bahkan jika mereka tidak akan pernah ditugaskan kembali (dengan pengecualian yang jelas ketika mereka perlu digunakan dalam kelas batin). Akhir-akhir ini, bagaimanapun, saya telah menemukan kode yang digunakan final kapan saja bisa, yang saya kira secara teknis memberikan lebih banyak informasi.

Tidak lagi percaya diri dengan gaya pemrograman saya, saya bertanya-tanya apa kelebihan dan kekurangan lain dari menerapkan final di mana saja, apa gaya industri yang paling umum, dan mengapa.

114
Oak

Saya menggunakan final dengan cara yang sama seperti Anda. Bagi saya itu terlihat berlebihan pada variabel lokal dan parameter metode, dan tidak menyampaikan informasi tambahan yang berguna.

Satu hal penting adalah bahwa berusaha untuk menjaga metode saya pendek dan bersih, masing-masing melakukan satu tugas. Dengan demikian, variabel dan parameter lokal saya memiliki cakupan yang sangat terbatas, dan hanya digunakan untuk satu tujuan. Ini meminimalkan kemungkinan penugasan kembali secara tidak sengaja.

Selain itu, seperti yang Anda ketahui, final tidak menjamin bahwa Anda tidak dapat mengubah nilai/status variabel (tidak bernilai). Hanya bahwa Anda tidak dapat menetapkan kembali referensi ke objek yang pernah diinisialisasi. Dengan kata lain, ini hanya bekerja dengan variabel tipe primitif atau tidak berubah. Mempertimbangkan

final String s = "forever";
final int i = 1;
final Map<String, Integer> m = new HashMap<String, Integer>();

s = "never"; // compilation error!
i++; // compilation error!
m.put(s, i); // fine

Ini berarti bahwa dalam banyak kasus masih tidak membuatnya lebih mudah untuk memahami apa yang terjadi di dalam kode, dan kesalahpahaman ini sebenarnya dapat menyebabkan bug halus yang sulit dideteksi.

68
Péter Török

Java gaya dan pemikiran pemrograman Anda baik-baik saja - tidak perlu meragukan diri Anda di sana.

Di sisi lain, saya merasa itu jauh kurang berguna dengan penduduk setempat dan parameter, dan biasanya saya menghindari menandai mereka sebagai final bahkan jika mereka tidak akan pernah ditugaskan kembali (dengan pengecualian yang jelas ketika mereka perlu digunakan di kelas dalam ).

Inilah sebabnya mengapa Anda harus menggunakan kata kunci final. Anda menyatakan bahwa ANDA tahu itu tidak akan pernah ditugaskan kembali, tetapi tidak ada orang lain yang tahu itu. Menggunakan final segera menghapus kode Anda sedikit lebih banyak.

66
J.K.

Salah satu keuntungan menggunakan final/const sedapat mungkin adalah dapat mengurangi beban mental pembaca kode Anda.

Dia dapat yakin, bahwa nilai/referensi tidak pernah diubah nanti. Jadi dia tidak perlu memperhatikan modifikasi untuk memahami perhitungannya.

Saya telah berubah pikiran mengenai hal ini setelah mempelajari bahasa pemrograman murni-fungsional. Boy, betapa meringankannya, jika Anda bisa mempercayai "variabel" untuk selalu memegang nilai awalnya.

32
LennyProgrammers

Saya menganggap final dalam parameter metode dan variabel lokal sebagai noise kode. Java bisa sangat panjang (terutama dengan obat generik) - tidak perlu membuatnya lagi.

Jika pengujian unit ditulis dengan benar, menetapkan parameter yang "berbahaya" akan diambil, jadi seharusnya tidak pernah sebenarnya menjadi masalah. Kejelasan visual lebih penting daripada menghindari bug mungkin yang tidak diambil karena tes unit Anda memiliki cakupan yang tidak memadai.

Alat-alat seperti FindBugs dan CheckStyle yang dapat dikonfigurasikan untuk memecah bangunan jika tugas dibuat untuk parameter atau variabel lokal, jika Anda sangat peduli tentang hal-hal seperti itu.

Tentu saja, jika Anda perl untuk membuatnya final, misalnya karena Anda menggunakan nilai dalam kelas anonim, maka tidak ada masalah - itu solusi paling sederhana yang paling bersih.

Terlepas dari efek yang jelas dari menambahkan kata kunci tambahan ke parameter Anda, dan dengan demikian IMHO menyamarkannya, menambahkan parameter akhir ke metode sering dapat membuat kode dalam tubuh metode menjadi kurang mudah dibaca, yang membuat kode lebih buruk - menjadi "baik", kode harus mudah dibaca dan sesederhana mungkin. Sebagai contoh buat-buat, katakan saya punya metode yang perlu bekerja kasus tidak sensitif.

Tanpa final:

public void doSomething(String input) {
    input = input.toLowerCase();
    // do a few things with input
}

Sederhana. Bersih. Semua orang tahu apa yang terjadi.

Sekarang dengan 'final', opsi 1:

public void doSomething(final String input) {
    final String lowercaseInput = input.toLowerCase();
    // do a few things with lowercaseInput
}

Sementara membuat parameter final menghentikan pembuat kode menambahkan lebih jauh dari berpikir dia bekerja dengan nilai asli, ada risiko yang sama bahwa kode lebih lanjut dapat menggunakan input bukan lowercaseInput , yang seharusnya tidak dan yang tidak dapat dilindungi, karena Anda tidak dapat membawanya keluar dari ruang lingkup (atau bahkan menetapkan null ke input jika itu bahkan akan membantu).

Dengan 'final', opsi 2:

public void doSomething(final String input) {
    // do a few things with input.toLowerCase()
}

Sekarang kita baru saja membuat lebih banyak noise kode dan memperkenalkan hit kinerja karena harus memanggil toLowerCase() n kali.

Dengan 'final', opsi 3:

public void doSomething(final String input) {
    doSomethingPrivate(input.toLowerCase());
}

/** @throws IllegalArgumentException if input not all lower case */
private void doSomethingPrivate(final String input) {
    if (!input.equals(input.toLowerCase())) {
        throw new IllegalArgumentException("input not lowercase");
    }
    // do a few things with input
}

Bicara tentang kebisingan kode. Ini adalah kecelakaan kereta api. Kami punya metode baru, blok pengecualian yang diperlukan, karena kode lain mungkin salah memanggilnya. Lebih banyak unit test untuk mencakup pengecualian. Semua untuk menghindari satu garis sederhana, dan IMHO lebih disukai dan tidak berbahaya.

Ada juga masalah bahwa metode tidak boleh terlalu lama sehingga Anda tidak dapat dengan mudah menerimanya secara visual dan mengetahui sekilas bahwa penugasan ke parameter telah terjadi.

Saya pikir itu adalah praktik/gaya yang baik bahwa jika Anda menetapkan ke parameter Anda melakukannya setiap awal dalam metode, lebih disukai baris pertama atau langsung setelah pengecekan input dasar, efektif mengganti untuk seluruh metode, yang memiliki efek konsisten dalam metode. Pembaca tahu untuk mengharapkan penugasan apa pun menjadi jelas (dekat deklarasi tanda tangan) dan di tempat yang konsisten, yang sangat memitigasi masalah yang ingin dihindari dengan menambahkan tugas akhir. Sebenarnya saya jarang menetapkan parameter, tetapi jika saya melakukannya saya selalu melakukannya di bagian atas metode.


Perhatikan juga bahwa final tidak benar-benar melindungi Anda seperti itu pada awalnya tampak:

public void foo(final Date date) {
    date.setTime(0); 
    // code that uses date
}

final tidak sepenuhnya melindungi Anda kecuali tipe parameternya primitif atau tidak dapat diubah.

22
Bohemian

Saya membiarkan Eclipse meletakkan final sebelum setiap variabel lokal, karena saya menganggapnya untuk membuat program lebih mudah dibaca. Saya tidak membuatnya dengan parameter, karena saya ingin menyimpan daftar parameter sesingkat mungkin, idealnya harus sesuai dalam satu baris.

7
maaartinus