Apakah / mengapa Java perlu memiliki void
metode? Referensi :
Metode apa pun yang dinyatakan batal tidak mengembalikan nilai.
Sejauh yang saya bisa pikirkan, setiap penggunaan void
akan lebih baik dilayani dengan mengembalikan bendera status, objek yang dipanggil, atau null
.
Ini akan membuat setiap panggilan pernyataan yang ditugaskan, dan akan memfasilitasi pola pembangun dan metode chaining. Metode yang hanya digunakan untuk efeknya biasanya akan mengembalikan boolean atau Success
tipe generik atau memberikan pengecualian pada kegagalan.
java
programming-languages
return-type
marisbest2
sumber
sumber
Jawaban:
Karena ada perbedaan antara "Fungsi ini dapat berhasil atau gagal dan cukup sadar sehingga dapat membedakan" dan "Tidak ada umpan balik tentang efek fungsi ini." Tanpa
void
, Anda akan terus-menerus memeriksa kode sukses dan percaya bahwa Anda sedang menulis perangkat lunak yang kuat, padahal sebenarnya Anda tidak melakukan hal semacam itu.sumber
void
tidak mengatakan apa-apa tentang apakah metode atau fungsi cukup sadar untuk melempar yang sesuai.void
tipe, dan Java dirancang untuk mengikuti banyak konvensi dari keluarga bahasa C.Success
tipe generik "? Pada kenyataannya, nilai pengembalian untuk menunjukkan keberhasilan bahkan kurang penting di Jawa daripada di C, karena Jawa memiliki pengecualian untuk menunjukkan kegagalan dan C tidak.sumber
Void
bertindak sebagai tipe Unit (misalnya untuk Generik), meskipun sayangnya, ini berbeda darivoid
(catatan: kucing yang suka diemong mati setiap kali Anda menemukan tipe baru untuk memperbaiki tipe yang Anda buat di versi sebelumnya). Jika ada yang tidak terbiasa dengan tipe Unit, ini adalah pengantar yang layak: en.wikipedia.org/wiki/Unit_typenull
(sebenarnya ini adalah satu-satunya pilihan), tetapi null adalah hal yang istimewa, nilai jenis referensi apa pun di Jawa mungkin nol (ini adalah kesalahan lain dalam desain bahasa). Dan, seperti yang saya katakan sebelumnya, jika Anda menggunakanVoid
tipe kembali bukanvoid
tanda, kompiler Java bukan teman Anda.null
. Fakta bahwanull
anggota adalah tipe yang paling tidak relevan dengan apakahVoid
tipe unit.The original alasan mengapa bahasa memiliki
void
tipe ini karena seperti diC
, pencipta bahasa tidak ingin tidak perlu mempersulit sintaks dari bahasa dengan prosedur dan fungsi s cara Pascal lakukan.Itulah alasan aslinya.
Saran Anda:
Itu tidak-tidak. Kami tidak menggunakan bendera status. Jika terjadi kesalahan, kami melaporkannya melalui pengecualian.
Gaya doa yang lancar adalah perkembangan baru-baru ini. Banyak programmer yang sangat senang menggunakan lancar hari ini dan memutar mata mereka jika mereka harus menggunakan antarmuka yang tidak mendukung itu bahkan tidak dilahirkan ketika Java dibuat.
Itu akan memaksa Anda untuk mendeklarasikan metode sebagai mengembalikan sesuatu, padahal sebenarnya itu tidak mengembalikan apa pun, jadi itu akan sangat membingungkan bagi seseorang yang sedang melihat antarmuka yang mencoba mencari tahu apa fungsinya. Orang pasti akan menemukan beberapa kelas yang tidak berguna yang berarti "tidak ada nilai kembali" sehingga semua fungsi yang tidak memiliki apa pun untuk dikembalikan dapat mengembalikan referensi nol ke kelas seperti itu. Itu akan kikuk. Untungnya, ada solusi untuk ini, begitulah namanya
void
. Dan itulah jawaban untuk pertanyaan Anda.sumber
int
, jadi kata kunci ditambahkan setelah K & R untuk menunjukkan 'tipe kembali'.Beberapa metode, seperti
System.out.println
tidak mengembalikan apa pun yang bermanfaat, tetapi disebut murni untuk efek samping ini.void
adalah indikator yang bermanfaat untuk kompiler dan bagi pembaca kode yang tidak mengembalikan nilai berguna.Mengembalikan
null
bukanvoid
berarti Anda hanya akan mendapatkanNullPointerException
momen saat Anda menggunakan nilai ini untuk apa pun. Jadi Anda menukar kesalahan waktu kompilasi dengan kesalahan runtime yang jauh lebih buruk. Selain itu, Anda harus mendefinisikan tipe pengembalian sebagaiObject
, yang akan menyesatkan dan membingungkan. (Dan merantai masih tidak akan berhasil.)Kode status biasanya digunakan untuk menunjukkan kondisi kesalahan, tetapi Java memiliki pengecualian untuk tujuan ini.
Pengembalian
this
tidak dimungkinkan dari metode statis.Mengembalikan
Success
objek generik tidak akan memiliki tujuan yang bermanfaat.sumber
Salah satu alasannya adalah bahwa bisa menyesatkan untuk mengembalikan apa pun selain, katakanlah
null
,. Contoh:Apa yang harus
Arrays.sort(a)
dikembalikan?Jika Anda berargumen bahwa itu
a
harus dikembalikan sehingga panggilan itu dapat dirantai (yang nampaknya merupakan tanggapan Anda berdasarkan pertanyaan Anda), maka tidak lagi jelas apakah nilai pengembalian adalah salinan dari objek asli, atau objek asli itu sendiri . Keduanya mungkin. Dan ya, Anda bisa memasukkannya ke dalam dokumentasi, tetapi cukup ambigu bahwa Anda tidak boleh membuat ambiguitas sejak awal.Di sisi lain, jika Anda berpendapat bahwa itu
null
harus dikembalikan, itu menimbulkan pertanyaan tentang informasi apa yang mungkin diberikan oleh nilai balik si penelepon, dan mengapa programmer harus dipaksa untuk menulisreturn null
ketika tidak ada informasi yang disampaikan.Dan jika Anda mengembalikan sesuatu yang benar-benar absurd (seperti panjangnya
a
) maka itu hanya membuat menggunakan nilai pengembalian itu benar-benar membingungkan - pikirkan saja betapa jauh lebih membingungkannyaint len = Arrays.sort(a)
daripada mengatakanint len = A.length
!sumber
return null;
- JVM bisa juga mengamanatkan bahwa jika kontrol jatuh dari akhir fungsi dengan cara lain selain eksplisitreturn
atauthrow
pernyataan,null
secara implisit dikembalikan ke pemanggil. IIRC C melakukan itu, kecuali bahwa nilai kembali tidak ditentukan dalam kasus itu (itu akan menjadi nilai apa pun yang terjadi di lokasi yang digunakan untuk nilai kembali pada saat itu).return
pernyataan. Sebagai gantinya, Anda mendapatkan kesalahan kompiler yang memberi tahu Anda tentang kesalahan Anda. Memasukkan implisitreturn null;
akan lebih baik daripada "perilaku tidak terdefinisi", tetapi tidak banyak. Itu akan berguna hanya ketika tipe kembali tidak memiliki arti, tetapi di mana kompiler menarik kesimpulan dari, bahwa nilai kembali tidak memiliki makna, padahal bukanvoid
?return
benar - benar tidak menambah nilai apa pun ...", yah, seperti yang dikatakan, tidak ada indikator untuk kompiler bahwa pengembalian tidak akan menambah nilai apa pun, jika tidak adavoid
jenis. Ini sebenarnya kebalikannya, asumsi pertama adalah bahwa metode yang menyatakan tipe pengembalian inginreturn
sesuatu yang berguna dari jenis itu. Dan kami belum berbicara tentang tipe primitif, yang tidak memilikinull
nilai, karenanya, nilai default apa pun yang disuntikkan oleh kompiler akan bertentangan dengan kisaran nilai pengembalian yang berpotensi bermanfaat.Mengembalikan
boolean
yang selalu sama dengantrue
yang Anda sarankan, tidak hanya sia-sia (nilai pengembalian tidak membawa informasi), tetapi sebenarnya akan menyesatkan. Sebagian besar waktu, yang terbaik untuk menggunakan jenis kembali yang hanya membawa informasi sebanyak benar-benar tersedia - itu sebabnya di Jawa Anda memilikiboolean
untuktrue
/false
daripada kembali sebuahint
dengan 4 miliar nilai yang mungkin. Demikian juga, mengembalikan aboolean
dengan dua nilai yang mungkin di mana hanya ada satu nilai yang mungkin ("kesuksesan generik"), akan menyesatkan.Itu juga akan menambah overhead kinerja yang tidak perlu.
Jika suatu metode hanya digunakan untuk efek sampingnya, tidak ada yang kembali, dan tipe pengembalian
void
mencerminkan hal itu. Potensi kesalahan langka dapat ditandai melalui pengecualian.Satu hal yang bisa diperbaiki, adalah membuat
void
tipe yang sebenarnya, seperti milik ScalaUnit
. Ini akan menyelesaikan beberapa masalah seperti penanganan obat generik.sumber
List.add
selalu kembalitrue
, tetapi itu karena kompatibel dengan kontrak yang lebih luasCollection.add
, jadiSet.add
dapat kembalitrue
ataufalse
.Java adalah bahasa yang relatif lama. Dan pada tahun 1995 (Ketika itu dibuat) dan tak lama kemudian programmer sangat peduli tentang jumlah waktu proses mengambil kendali prosesor serta konsumsi memori. Membatalkan kembali akan menghilangkan beberapa siklus jam dan sedikit konsumsi memori dari panggilan fungsi karena Anda tidak harus meletakkan nilai kembali pada tumpukan, dan Anda tidak perlu menghapusnya lagi.
Kode efisien tidak memberi Anda kembali sesuatu yang tidak akan pernah Anda gunakan, dan karenanya membatalkan sesuatu yang memiliki nilai pengembalian yang tidak berarti adalah praktik yang jauh lebih baik daripada mengembalikan nilai keberhasilan.
sumber
Saya sudah membaca argumen yang menyarankan bahwa opsi kedua (kembali
this
) harus menjadi pendekatan alih-alihvoid
. Ini adalah ide yang cukup bagus tetapi pendekatan gaya pembangun tidak populer pada saat Java dibuat. Jika itu sama populernya pada saat itu seperti sekarang, itu mungkin pendekatan yang diambil. Kembalinull
adalah ide IMO yang sangat buruk. Saya berharapnull
bahkan tidak dalam bahasa sama sekali.Masalahnya sekarang adalah bahwa jika suatu metode mengembalikan turunan dari tipe miliknya sendiri, tidak jelas apakah itu objek baru atau objek yang sama. Seringkali itu tidak (atau tidak seharusnya) penting tetapi di lain waktu itu penting. Saya kira bahasanya bisa diubah untuk secara implisit mengembalikan
this
metode yang kosong. Satu-satunya masalah yang dapat saya pikirkan dengan itu saat ini adalah bahwa jika metode ini kemudian diubah untuk mengembalikan objek baru dari jenis yang sama, tidak akan ada peringatan kompilasi tetapi itu mungkin bukan masalah besar. Sistem tipe saat ini tidak peduli dengan jenis perubahan ini sekarang. Bagaimana ini berinteraksi dengan warisan / antarmuka akan memerlukan beberapa pertimbangan tetapi itu akan memungkinkan API lama tanpa gaya builder dengan mudah disebut seolah-olah mereka melakukannya.sumber
null
bukan bagian dari bahasa, orang akan menggunakan segala macam nilai sentinel yang berarti "tolong abaikan nilai argumen / pengembalian ini, itu tidak mengandung nilai yang masuk akal". Masalah dengannull
bukanlah hal itu sendiri, hanya saja cenderung digunakan secara tidak benar. Saya berani bertaruh bahwa masalah ini hanya akan dilebih-lebihkan jika yang terstandarisasinull
akan diganti dengan segudang solusi khusus, di mana setiap implementasi akan berperilaku berbeda seperti diam-diam mengabaikan penggunaan, atau melemparkan pengecualian khusus alih-alih pengecualian penunjuk nol standar, dll.null
adalah tipe opsional yang tepat (seperti,Maybe
di Haskell). Masalah dengan nulls di Java adalah bahwa tidak ada cara yang waras untuk segera memutuskan apakah suatu nilai nullable dalam praktik atau tidak. Ini mengarah pada keduanya: pemrograman defensif yang tidak perlu (memeriksa nol di mana tidak ada gunanya, sehingga meningkatkan persentase kotoran dalam kode), dan NPEs yang tidak disengaja dalam produksi (jika lupa memeriksa di mana diperlukan). Ya, sebagian diselesaikan oleh anotasi tetapi mereka opsional, tidak selalu diperiksa, dll. Sehingga mereka tidak akan menyelamatkan Anda pada batas dengan kode pihak ketiga.null
berfungsi dengan baik untuk ini (fine = sederhana), tetapi nilai opsional terstandarisasi dengan semantik yang solid jelas merupakan opsi bagus lainnya (fine = safe).Aspek lain:
Java adalah bahasa statis dengan fitur yang cukup ketat. Ini berarti bahwa banyak hal yang cukup terbuka atau dinamis dalam bahasa lain (c / f Ruby, Lisp dll.) Sangat ditentukan.
Ini adalah keputusan desain umum. "Mengapa" sulit untuk dijawab (baik, karena perancang bahasa berpikir itu akan baik!). "Untuk apa" cukup jelas: memungkinkan kompiler mendeteksi banyak kesalahan, yang umumnya merupakan fitur yang cukup baik untuk bahasa apa pun. Kedua, itu membuatnya relatif mudah untuk berpikir tentang bahasa. Misalnya, relatif mudah untuk membuat pembenaran formal dalam (himpunan bagian) bahasa Jawa; sebagai perbandingan, itu akan menjadi hampir mustahil dalam bahasa yang dinamis seperti Ruby et al.
Pemikiran ini meresapi bahasa, misalnya, deklarasi paksa tentang kemungkinan pengecualian yang dapat dilemparkan oleh suatu metode, tipe
interface
vs yang terpisahclass
untuk menghindari pewarisan berganda yang ambigu, dan sebagainya. Untuk apa itu (OOP imperatif statis bahasa dunia nyata dengan fokus yang kuat pada penanganan kesalahan waktu kompilasi) hal-hal itu sebenarnya cukup elegan dan kuat. Mereka datang lebih dekat ke bahasa teoretis (sains) yang sengaja dibuat hanya untuk mengeksplorasi beberapa masalah ini daripada bahasa dunia nyata lainnya sebelumnya (pada waktu itu, ingatlah).Begitu. Memiliki
void
tipe yang ketat adalah pesan yang jelas: metode ini tidak mengembalikan apa pun, titik. Itu adalah apa adanya. Menggantinya dengan penegakan untuk selalu mengembalikan sesuatu akan mengarah pada perilaku yang jauh lebih dinamis (seperti di Ruby di mana setiap def memiliki nilai pengembalian yang eksplisit atau implisit, selalu), yang akan berdampak buruk bagi provabilitas dan alasan; atau untuk mengasapi dengan menggunakan mekanisme lain di sini.(Dan NB, Ruby (misalnya) menangani hal ini secara berbeda, dan solusinya masih dapat diterima seperti halnya Java, karena ia memiliki filosofi yang sama sekali berbeda. Misalnya ia melempar provabilitas dan kewajaran sepenuhnya dari jendela sambil menempatkan fokus besar pada ekspresi bahasa yang sangat tinggi.)
sumber