Saya baru-baru ini membaca tentang ini dan melihat orang-orang menggunakan kelas ini, tetapi dalam hampir semua kasus, penggunaan null
akan berhasil juga - jika tidak lebih intuitif. Dapatkah seseorang memberikan contoh konkret di mana Optional
akan mencapai sesuatu yang null
tidak bisa atau dengan cara yang jauh lebih bersih? Satu-satunya hal yang dapat saya pikirkan adalah menggunakannya dengan Maps
tidak menerima null
kunci, tetapi bahkan itu dapat dilakukan dengan sisi "pemetaan" dari nilai null. Adakah yang bisa memberi saya argumen yang lebih meyakinkan? Terima kasih.
89
Jawaban:
Anggota tim jambu di sini.
Mungkin satu-satunya kelemahan terbesar
null
adalah tidak jelas apa artinya dalam konteks tertentu: tidak memiliki nama ilustrasi. Itu tidak selalu jelas yangnull
berarti "tidak ada nilai untuk parameter ini" - heck, sebagai nilai yang dikembalikan, terkadang itu berarti "kesalahan", atau bahkan "berhasil" (!!), atau hanya "jawaban yang benar adalah tidak ada".Optional
sering kali merupakan konsep yang sebenarnya Anda maksud saat membuat variabel menjadi nullable, tetapi tidak selalu. Jika tidak, kami menyarankan Anda untuk menulis kelas Anda sendiri, mirip denganOptional
tetapi dengan skema penamaan yang berbeda, untuk memperjelas apa yang sebenarnya Anda maksud.Tetapi saya akan mengatakan keuntungan terbesar
Optional
tidak dalam keterbacaan: keuntungannya adalah bukti-kebodohannya. Ini memaksa Anda untuk secara aktif memikirkan kasus absen jika Anda ingin program Anda untuk dikompilasi sama sekali, karena Anda harus secara aktif membuka bungkusOptional
dan menangani kasus itu. Null membuatnya sangat mudah untuk melupakan sesuatu, dan meskipun FindBugs membantu, saya rasa itu tidak mengatasi masalah dengan baik. Ini sangat relevan ketika Anda mengembalikan nilai yang mungkin "ada" atau tidak. Anda (dan lain-lain) jauh lebih mungkin untuk melupakan bahwaother.method(a, b)
bisa mengembalikannull
nilai dari Anda mungkin lupa bahwaa
bisanull
ketika Anda menerapkanother.method
. KembaliOptional
membuat penelepon tidak mungkin melupakan kasus itu, karena mereka harus membuka sendiri objeknya.Untuk alasan ini, kami merekomendasikan agar Anda menggunakan
Optional
sebagai tipe kembalian untuk metode Anda, tetapi tidak harus dalam argumen metode Anda.(Omong-omong, ini benar-benar disebutkan dari diskusi di sini .)
sumber
Map
mengembalikannull
jika kunci tidak dipetakan, tetapi ingat bahwa jika Anda melakukannyamap.put(key, null)
, makamap.containsKey(key)
akan kembalitrue
tetapimap.get(key)
akan kembalinull
.Optional
dapat berguna dalam membersihkan perbedaan antara kasus "yang dipetakan secara eksplisit ke null" dan kasus "tidak ada di peta". Saya akan mengabulkan bahwa ituOptional
dapat disalahgunakan, tetapi saya belum yakin bahwa kasus yang Anda gambarkan adalah pelecehan.Optional<T>
apakah itu nilai "ditemukan, tetapi tidak valid". Atau lebih tepatnya,Optional<T>
adalah cara untuk menghias jenis apa punT
dengan nilai ekstra "ditemukan, tetapi tidak valid" - membuat jenis baru dengan menggabungkan dua jenis yang ada. Jika Anda memiliki seratus kelas, akan berantakan jika Anda harus membuat nilai "ditemukan, tetapi tidak valid" untuk masing-masing kelas, tetapiOptional<T>
dapat dengan mudah berfungsi untuk semuanya.Ini benar-benar terlihat seperti
Maybe
pola Monad dari Haskell.Anda harus membaca berikut ini, Wikipedia Monad (pemrograman fungsional) :
Dan baca Dari Opsional ke Monad dengan Jambu Biji di Blog Kerflyn, yang membahas tentang Pilihan Jambu Biji yang digunakan sebagai Monad:
Sunting: Dengan Java8, ada Opsional bawaan yang memiliki operator monadik seperti
flatMap
. Ini telah menjadi topik yang kontroversial tetapi akhirnya diterapkan.Lihat http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html
public Optional<String> tryFindSimilar(String s) //... Optional<Optional<String>> bad = opt.map(this::tryFindSimilar); Optional<String> similar = opt.flatMap(this::tryFindSimilar);
The
flatMap
operator adalah penting untuk memungkinkan operasi monadik, dan izin untuk dengan mudah rantai panggilan yang semua kembali Opsional hasil.Pikirkan tentang itu, jika Anda menggunakan
map
operator 5 kali Anda akan berakhir denganOptional<Optional<Optional<Optional<Optional<String>>>>>
, sedangkan menggunakanflatMap
akan memberi AndaOptional<String>
Sejak Java8 saya lebih suka tidak menggunakan Guava's Opsional yang kurang bertenaga.
sumber
Salah satu alasan bagus untuk menggunakannya adalah karena itu membuat null Anda sangat berarti. Alih-alih mengembalikan null yang bisa berarti banyak hal (seperti kesalahan, atau kegagalan, atau kosong, dll), Anda dapat memasukkan 'nama' ke null Anda. Lihat contoh ini:
mari kita tentukan POJO dasar:
class PersonDetails { String person; String comments; public PersonDetails(String person, String comments) { this.person = person; this.comments = comments; } public String getPerson() { return person; } public String getComments() { return comments; }
}
Sekarang mari kita gunakan POJO sederhana ini:
public Optional<PersonDetails> getPersonDetailstWithOptional () { PersonDetails details = null; /*details of the person are empty but to the caller this is meaningless, lets make the return value more meaningful*/ if (details == null) { //return an absent here, caller can check for absent to signify details are not present return Optional.absent(); } else { //else return the details wrapped in a guava 'optional' return Optional.of(details); } }
Sekarang mari kita hindari penggunaan null dan lakukan pemeriksaan dengan Opsional sehingga berarti
public void checkUsingOptional () { Optional<PersonDetails> details = getPersonDetailstWithOptional(); /*below condition checks if persons details are present (notice we dont check if person details are null, we use something more meaningful. Guava optional forces this with the implementation)*/ if (details.isPresent()) { PersonDetails details = details.get(); // proceed with further processing logger.info(details); } else { // do nothing logger.info("object was null"); } assertFalse(details.isPresent()); }
jadi pada akhirnya ini adalah cara untuk membuat nulls bermakna, & mengurangi ambiguitas.
sumber
Keuntungan terpenting dari Opsional adalah ia menambahkan lebih banyak detail pada kontrak antara pelaksana dan pemanggil suatu fungsi. Untuk alasan ini berguna untuk parameter dan tipe kembalian.
Jika Anda membuat konvensi untuk selalu memiliki
Optional
kemungkinan objek null, Anda menambahkan lebih banyak klarifikasi untuk kasus seperti:Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)
Kontrak di sini dengan jelas menetapkan bahwa ada kemungkinan bahwa hasil tidak dikembalikan tetapi juga menunjukkan bahwa hasil tersebut akan berfungsi dengan
from
danto
sebagai tidak ada.Optional<Integer> maxPrime(Optional<Integer> from, Integer to)
Kontrak menetapkan bahwa from adalah opsional sehingga nilai yang tidak ada mungkin memiliki arti khusus seperti mulai dari 2. Saya dapat mengharapkan bahwa nilai null untuk
to
parameter akan memunculkan pengecualian.Jadi bagian yang baik dari menggunakan Opsional adalah bahwa kontrak menjadi deskriptif (mirip dengan
@NotNull
anotasi) tetapi juga formal karena Anda harus menulis kode.get()
untuk mengatasinyaOptional
.sumber