Ekspresi Lambda vs referensi metode [ditutup]

114

IntelliJ terus menyarankan saya untuk mengganti ekspresi lambda saya dengan referensi metode.

Apakah ada perbedaan obyektif di antara keduanya?

Gerard
sumber
4
Tidak juga, saya tidak melihat objek apa pun! Sepertinya panggilan statis bagi saya
Gerard
9
Tentu saja! Tapi "tidakkah kamu menemukan" juga ... Ini masalah selera, saya lebih khawatir tentang aspek yang lebih teknis. Faktanya, seperti yang Anda katakan bahwa mereka sama, itu adalah jawaban yang bagus untuk saya. Bagaimanapun, seperti yang diusulkan IntelliJ, saya rasa secara umum lebih dihargai untuk melihat referensi metode daripada lambda (bukan untuk saya).
Gerard
15
Kode ekspresi lambda dikompilasi menjadi metode sintetis sementara referensi metode bekerja tanpa (pengecualian: konstruksi khusus seperti Type[]::new). Kelas anonim yang dibuat pada waktu proses akan sama. JRE tidak membuat perbedaan apa pun di antara keduanya. Jadi menggunakan referensi metode akan menghemat satu metode dalam kode terkompilasi Anda, di sisi lain, Anda tidak dapat berhenti pada mereka saat melakukan debugging langkah demi langkah…
Holger
6
Sekarang pertanyaannya akan ditutup ... Sayang sekali untuk semua pengguna seperti saya yang tidak tahu perbedaan antara lambda dan referensi, bahkan jika tidak ada yang menentukan. Saya juga bertanya-tanya mengapa tidak ada yang berani menjawab itu? Itulah jawaban yang tepat untuk saya.
Gerard
3
Menjawab pertanyaan tertutup dua tahun mungkin ide yang buruk tetapi bagi mereka yang BENAR-BENAR MEMBACA pertanyaan ini adalah apa yang dikatakan oleh tutorial Oracle ( docs.oracle.com/javase/tutorial/java/javaOO/… ): Referensi metode ... adalah ekspresi lambda yang ringkas dan mudah dibaca untuk metode yang sudah memiliki nama.
besok

Jawaban:

187

Izinkan saya menawarkan beberapa perspektif tentang mengapa kami menambahkan fitur ini ke bahasa, padahal jelas kami tidak benar-benar perlu (semua referensi metode dapat diekspresikan sebagai lambda.)

Perhatikan bahwa tidak ada jawaban yang benar . Siapapun yang mengatakan "selalu gunakan metode ref daripada lambda" atau "selalu gunakan lambda alih-alih metode ref" harus diabaikan.

Pertanyaan ini sangat mirip dengan semangat "kapan saya harus menggunakan kelas bernama vs kelas anonim"? Dan jawabannya sama: jika menurut Anda lebih mudah dibaca . Tentu ada kasus yang pasti satu atau pasti yang lain tapi ada sejumlah abu-abu di tengah, dan penilaian harus digunakan.

Teori di balik referensi metode sederhana: nama penting . Jika sebuah metode memiliki sebuah nama, maka merujuknya dengan namanya, bukan dengan sekumpulan kode yang pada akhirnya hanya berbalik dan memanggilnya, seringkali (tetapi tidak selalu!) Lebih jelas dan mudah dibaca.

Argumen tentang kinerja atau tentang menghitung karakter sebagian besar merupakan masalah besar, dan Anda harus mengabaikannya. Tujuannya adalah menulis kode yang menjelaskan apa yang dilakukannya. Sangat sering (tetapi tidak selalu!) Ref metode menang pada metrik ini, jadi kami memasukkannya sebagai opsi, untuk digunakan dalam kasus tersebut.

Pertimbangan utama tentang apakah referensi metode memperjelas atau mengaburkan maksud adalah apakah sudah jelas dari konteks apa bentuk fungsi yang diwakili. Dalam beberapa kasus (misalnya, map(Person::getLastName)cukup jelas dari konteks bahwa fungsi yang memetakan satu hal ke hal lain diperlukan, dan dalam kasus seperti ini, referensi metode bersinar. Dalam kasus lain, menggunakan metode ref mengharuskan pembaca bertanya-tanya tentang jenis apa fungsi dijelaskan; ini adalah tanda peringatan bahwa lambda mungkin lebih mudah dibaca, meskipun lebih panjang.

Akhirnya, apa yang kami temukan adalah bahwa kebanyakan orang pada awalnya menjauh dari referensi metode karena mereka merasa lebih baru dan lebih aneh daripada lambda, dan awalnya menganggapnya "kurang dapat dibaca", tetapi seiring waktu, ketika mereka terbiasa dengan sintaks, umumnya mengubah perilaku mereka dan tertarik pada referensi metode bila mereka bisa. Jadi ketahuilah bahwa reaksi awal subjektif Anda yang "kurang terbaca" hampir pasti memerlukan beberapa aspek bias kekeluargaan, dan Anda harus memberi diri Anda kesempatan untuk merasa nyaman dengan keduanya sebelum memberikan opini gaya.

Brian Goetz
sumber
25
@Gerard Terima kasih akan menjadi jawaban yang lebih baik.
Yassin Hajaj
3
@ Gerard Kedengarannya Brian mengatakan "Tidak, tidak ada"
dj18
Brian, saya mendapatkan hasil yang berbeda menggunakan referensi metode dan lambda untuk metode yang sama. Bukankah seharusnya mereka dapat dipertukarkan?
Michel Feinstein
@mFeinstein Untuk setiap metode ref, ada lambda yang setara (yang mungkin Anda gunakan atau tidak). Posting kode sebagai pertanyaan?
Brian Goetz
Saya ingin, tetapi saya khawatir kodenya mungkin terlalu besar, karena ini adalah Android LiveData, di dalam a Fragment, yang saya ubah menjadi Eventyang dipicu oleh ViewModel... dan perilaku yang berbeda terjadi ketika Android kembali ke yang sama Fragment.. . jadi saya kesulitan menyederhanakannya untuk sebuah pertanyaan
Michel Feinstein
10

Ekspresi lambda panjang yang terdiri dari beberapa pernyataan dapat mengurangi keterbacaan kode Anda. Dalam kasus seperti itu, mengekstrak pernyataan tersebut dalam sebuah metode dan merujuknya mungkin merupakan pilihan yang lebih baik.

Alasan lainnya mungkin dapat digunakan kembali . Alih-alih menyalin & menempelkan ekspresi lambda dari beberapa pernyataan, Anda dapat membuat metode dan memanggilnya dari berbagai tempat kode Anda.

ovunccetin.dll
sumber
3
Bandingkan: houses.map(House::getName)dan houses.map(h -> h.getName()). Lambda membutuhkan dua karakter lebih sedikit. Memang benar bahwa jenisnya tidak eksplisit, tetapi setiap IDE akan memberi tahu Anda, dan selain itu, lambda harus digunakan ketika jenisnya jelas. Saya mungkin setuju dengan Anda dengan penggunaan kembali, tetapi lambda sangat kecil sehingga mereka dapat dirantai alih-alih membuat metode spesifik yang besar. Dalam hal ini, metode kecil lebih dapat digunakan kembali daripada beberapa metode besar dan kompleks, dan karena kejelasan lambda (dan sampai tingkat tertentu, verbositas) metode tersebut masih mudah dibaca.
Gerard
11
Saya dengan Gerald. Keterbacaan sebenarnya terganggu ketika Anda memindahkan kode, jadi Anda harus melompat ke sana untuk terus membaca, lalu kembali lagi. Anda ingin memiliki semua kode yang relevan di tempat yang sama. Juga, Housemerupakan contoh yang sangat jinak; tentang apa ThreeStoryRedBrickHouseWithBlueDoors. Saya lebih suka referensi metode untuk lambda banyak argumen, dan terkadang untuk menekankan bahwa lambda hanya tentang satu pemanggilan metode. Ada sedikit kesalahan dengan referensi metode: Anda mungkin salah mengeja argumen di situs penggunaan, secara tidak sengaja merujuk ke variabel dari cakupan luar, dll.
Marko Topolnik
@ Gerard Saya tidak setuju dengan pernyataan pertama Anda. Jika Anda menggunakan nama metode yang mendeskripsikan dengan baik dan jika Anda mengekstrak tumpukan kode yang besar, memindahkan kode meningkatkan keterbacaan. Jika Anda menggunakan nama metode yang mengaburkan, saya setuju dengan Anda.
Torsten