Ambil dua contoh kode:
if(optional.isPresent()) {
//do your thing
}
if(variable != null) {
//do your thing
}
Sejauh yang saya tahu perbedaan yang paling jelas adalah bahwa Opsional membutuhkan pembuatan objek tambahan.
Namun, banyak orang sudah mulai mengadopsi Opsional dengan cepat. Apa keuntungan menggunakan opsional dibandingkan cek nol?
if
pernyataannya sangaaaat dekade terakhir, dan semua orang menggunakan abstraksi monad dan lambda sekarang.if(x.isPresent) fails_on_null(x.get)
Anda keluar dari sistem tipe dan harus menjaga jaminan bahwa kode tidak akan memecahkan "di kepala Anda" selama jarak (diakui pendek) antara kondisi dan pemanggilan fungsi. Dalamoptional.ifPresent(fails_on_null)
tipe sistem membuat jaminan ini untuk Anda, dan Anda tidak perlu khawatir.Optional.ifPresent
(dan berbagai konstruksi Java lainnya) adalah Anda hanya dapat memodifikasi variabel final secara efektif dan tidak dapat membuang pengecualian yang diperiksa. Itulah alasan yang cukup sering dihindariifPresent
, sayangnya.Jawaban:
Optional
memanfaatkan tipe sistem untuk melakukan pekerjaan yang seharusnya Anda lakukan semua di kepala Anda: mengingat apakah referensi yang diberikan mungkin atau tidaknull
. Ini bagus. Itu selalu pintar untuk membiarkan kompiler menangani obat bius yang membosankan, dan menyimpan pemikiran manusia untuk pekerjaan yang kreatif dan menarik.Tanpa
Optional
, setiap referensi dalam kode Anda seperti bom yang tidak meledak. Mengaksesnya dapat melakukan sesuatu yang bermanfaat, atau dapat menghentikan program Anda dengan pengecualian.Dengan Opsional dan tanpa
null
, setiap akses ke referensi normal berhasil, dan setiap referensi ke Opsional berhasil kecuali itu tidak disetel dan Anda gagal memeriksa untuk itu. Itu adalah kemenangan besar dalam pemeliharaan.Sayangnya, sebagian besar bahasa yang sekarang menawarkan
Optional
belum dihapuskannull
, jadi Anda hanya dapat mengambil untung dari konsep tersebut dengan melembagakan kebijakan ketat "sama sekali tidaknull
, pernah". Oleh karena itu,Optional
misalnya Java tidak semenarik yang seharusnya.sumber
Optional
hanya untuk mengingatkan Anda bahwa nilainya bisa nolSebuah
Optional
memasukkan pengetikan yang lebih kuat ke dalam operasi yang mungkin gagal, seperti yang dijawab oleh jawaban lain, tetapi itu jauh dari hal yang paling menarik atau berharga yang dibahasOptionals
. Jauh lebih berguna adalah kemampuan untuk menunda atau menghindari memeriksa kegagalan, dan dengan mudah menyusun banyak operasi yang mungkin gagal.Pertimbangkan jika Anda memiliki
optional
variabel dari kode contoh Anda, maka Anda harus melakukan dua langkah tambahan yang masing-masing berpotensi gagal. Jika ada langkah yang gagal, Anda ingin mengembalikan nilai default. MenggunakanOptionals
dengan benar, Anda berakhir dengan sesuatu seperti ini:Dengan
null
saya harus memeriksa tiga kalinull
sebelum melanjutkan, yang menambahkan banyak kerumitan dan sakit kepala pemeliharaan kode.Optionals
memiliki pemeriksaan bawaan keflatMap
danorElse
fungsi.Catatan saya tidak menelepon
isPresent
sekali, yang harus Anda anggap sebagai bau kode saat menggunakanOptionals
. Itu tidak berarti Anda tidak boleh menggunakanisPresent
, hanya saja Anda harus memeriksa dengan cermat setiap kode yang ada, untuk melihat apakah ada cara yang lebih baik. Jika tidak, Anda benar, Anda hanya mendapatkan manfaat keamanan tipe marginal daripada menggunakannull
.Perhatikan juga bahwa saya tidak khawatir tentang merangkum semua ini menjadi satu fungsi, untuk melindungi bagian lain dari kode saya dari null pointer dari hasil antara. Jika lebih masuk akal untuk memiliki saya
.orElse(defaultValue)
di fungsi lain misalnya, saya memiliki keraguan jauh lebih sedikit tentang meletakkannya di sana, dan itu jauh lebih mudah untuk menyusun operasi antara fungsi yang berbeda sesuai kebutuhan.sumber
Ini menyoroti kemungkinan nol sebagai respons yang valid, yang sering diasumsikan orang (benar atau salah) tidak akan dikembalikan. Menyoroti beberapa kali ketika null valid memungkinkan menghilangkan membuang sampah sembarangan kode Anda dengan sejumlah besar cek nol sia-sia.
Idealnya mengatur variabel ke nol akan menjadi kesalahan waktu kompilasi di mana saja tetapi dalam opsional; menghilangkan pengecualian null pointer runtime. Sayangnya kompatibilitas mundur menghalangi ini, sayangnya
sumber
Biarkan saya memberi Anda sebuah contoh:
Cukup jelas untuk apa metode ini dimaksudkan. Tetapi apa yang terjadi jika repositori tidak mengandung pengguna dengan id yang diberikan? Bisa melempar pengecualian atau mungkin mengembalikan nol?
Contoh kedua:
Sekarang, apa yang terjadi di sini jika tidak ada pengguna dengan id yang diberikan? Benar, Anda mendapatkan instance Optional.absent () dan Anda dapat memeriksanya dengan Optional.isPresent (). Metode tanda tangan dengan Opsional lebih eksplisit tentang kontraknya. Segera jelas, bagaimana metode ini seharusnya berperilaku.
Ini juga memiliki manfaat ketika membaca kode klien:
Saya telah melatih mata saya untuk melihat .get () sebagai kode bau langsung. Ini berarti bahwa klien sengaja mengabaikan kontrak dari metode yang dipanggil. Ini jauh lebih mudah untuk melihat ini daripada tanpa Opsional, karena dalam hal ini Anda tidak segera menyadari apa yang disebut metode kontrak (apakah itu memungkinkan nol atau tidak dalam pengembaliannya) sehingga Anda perlu memeriksanya terlebih dahulu.
Opsional digunakan dengan konvensi bahwa metode dengan tipe pengembalian Opsional tidak pernah mengembalikan nol dan biasanya juga dengan konvensi (kurang kuat) bahwa metode tanpa jenis pengembalian opsional tidak pernah mengembalikan nol (tetapi lebih baik untuk membubuhi keterangan dengan @Nonnull, @NotNull atau yang serupa) .
sumber
Sebuah
Optional<T>
memungkinkan Anda untuk memiliki "kegagalan" atau "tidak ada hasil" sebagai nilai respons / pengembalian yang valid untuk metode Anda (pikirkan, misalnya, pencarian basis data). MenggunakanOptional
daripada menggunakannull
untuk menunjukkan kegagalan / tidak ada hasil memiliki beberapa keuntungan:null
mungkin dikembalikan.null
seharusnya, setidaknya menurut pendapat saya, tidak digunakan untuk menunjukkan apa pun karena semantiknya mungkin tidak sepenuhnya jelas. Ini harus digunakan untuk memberi tahu pemulung bahwa objek yang sebelumnya dirujuk dapat dikumpulkan.Optional
kelas menyediakan banyak metode yang bagus untuk kondisional bekerja dengan nilai-nilai (misalnya,ifPresent()
) atau menetapkan nilai default dengan cara transparan (orElse()
).Sayangnya, itu tidak sepenuhnya menghapus perlunya
null
pemeriksaan dalam kode karenaOptional
objek itu sendiri masih mungkinnull
.sumber
Selain jawaban lain, keuntungan utama lainnya dari Opsional ketika menulis kode bersih adalah Anda bisa menggunakan ekspresi Lambda jika nilainya ada, seperti yang ditunjukkan di bawah ini:
sumber
Pertimbangkan metode berikut:
Sekarang mari kita lihat beberapa kode panggilan:
Hal ini menyebabkan berpotensi sulit untuk melacak kerusakan di tempat lain, karena
dance
tidak mengharapkan nol.Ini menyebabkan kesalahan kompilasi, karena tarian mengharapkan
Person
bukanOptional<Person>
Jika saya tidak memiliki seseorang, ini menyebabkan pengecualian pada baris ini, pada titik di mana saya secara tidak sah mencoba mengubah orang tersebut
Optional<Person>
menjadi Seseorang. Kuncinya adalah bahwa tidak seperti melewatkan nol, kecuali jejak ke sini, bukan beberapa lokasi lain dalam program.Untuk menyatukan semuanya: penyalahgunaan opsional menghasilkan lebih mudah untuk melacak masalah, penyalahgunaan nol menyebabkan sulit untuk melacak masalah.
sumber
Optional.get()
kode Anda ditulis dengan buruk - Anda seharusnya hampir tidak pernah menelepon Optional.get tanpa memeriksaOptional.isPresent()
terlebih dahulu (seperti yang ditunjukkan dalam OP) atau Anda dapat menulisoptionalPersion.ifPresent(myObj::dance)
.Di Objective-C, semua referensi objek adalah opsional. Karena itu, kode seperti yang Anda poskan konyol.
Kode seperti di atas tidak pernah terdengar dalam Objective-C. Sebaliknya, programmer hanya akan:
Jika
variable
berisi nilai, makadoThing
akan dipanggil di sana. Jika tidak, tidak ada salahnya. Program akan memperlakukannya sebagai larangan dan terus berjalan.Ini adalah manfaat nyata dari opsional. Anda tidak perlu membuang kode Anda
if (obj != nil)
.sumber
Masalah yang jelas di sini adalah bahwa jika "opsional" benar - benar hilang (yaitu nol) maka kode Anda akan meledak dengan NullReferenceException (atau serupa) yang mencoba memanggil metode apa pun pada referensi objek nol!
Anda mungkin ingin menulis metode Helper-class statis yang menentukan null-ness dari setiap jenis objek yang diberikan, seperti ini:
atau, mungkin, lebih bermanfaat:
Tetapi apakah salah satu dari ini benar-benar lebih dapat dibaca / dimengerti / dipelihara daripada yang asli?
sumber