Alasan Optional
ditambahkan ke Jawa adalah karena ini:
return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.getOrThrow(() -> new InternalError(...));
lebih bersih dari ini:
Method matching =
Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.getFirst();
if (matching == null)
throw new InternalError("Enclosing method not found");
return matching;
Maksud saya adalah bahwa Opsional ditulis untuk mendukung pemrograman fungsional , yang ditambahkan ke Jawa pada saat yang sama. (Contoh berasal dari blog oleh Brian Goetz . Contoh yang lebih baik mungkin menggunakan orElse()
metode ini, karena kode ini akan memunculkan pengecualian, tetapi Anda mendapatkan gambarnya.)
Tetapi sekarang, orang menggunakan Opsional untuk alasan yang sangat berbeda. Mereka menggunakannya untuk mengatasi kekurangan dalam desain bahasa. Kekurangannya adalah ini: Tidak ada cara untuk menentukan parameter API mana dan nilai pengembalian yang boleh nol. Mungkin disebutkan di javadocs, tetapi kebanyakan pengembang bahkan tidak menulis javadocs untuk kode mereka, dan tidak banyak yang akan memeriksa javadocs ketika mereka menulis. Jadi ini mengarah ke banyak kode yang selalu memeriksa nilai-nilai nol sebelum menggunakannya, meskipun mereka sering tidak mungkin menjadi nol karena mereka sudah divalidasi berulang kali sembilan atau sepuluh kali tumpukan panggilan.
Saya pikir ada kehausan nyata untuk menyelesaikan kekurangan ini, karena begitu banyak orang yang melihat kelas Opsional baru berasumsi tujuannya adalah untuk menambah kejelasan pada API. Itulah sebabnya orang-orang mengajukan pertanyaan seperti "apakah getter mengembalikan Opsional?" Tidak, mereka mungkin tidak boleh, kecuali jika Anda mengharapkan getter untuk digunakan dalam pemrograman fungsional, yang sangat tidak mungkin. Bahkan, jika Anda melihat di mana Opsional digunakan di Java API, itu terutama di kelas Stream, yang merupakan inti dari pemrograman fungsional. (Saya belum memeriksa dengan teliti, tetapi kelas Stream mungkin satu - satunya tempat yang mereka gunakan.)
Jika Anda berencana untuk menggunakan pengambil dalam sedikit kode fungsional, mungkin ide yang baik untuk memiliki pengambil standar dan yang kedua yang mengembalikan opsional.
Oh, dan jika Anda perlu kelas Anda menjadi serializable, Anda harus benar-benar tidak menggunakan Opsional.
Opsional adalah solusi yang sangat buruk untuk cacat API karena a) mereka sangat bertele-tele, dan b) Mereka tidak pernah dimaksudkan untuk menyelesaikan masalah itu sejak awal.
Solusi yang jauh lebih baik untuk cacat API adalah Pemeriksa Nullness . Ini adalah prosesor anotasi yang memungkinkan Anda menentukan parameter dan nilai pengembalian yang diizinkan menjadi nol dengan membubuhi keterangan dengan @Nullable. Dengan cara ini, kompiler dapat memindai kode dan mencari tahu apakah nilai yang benar-benar dapat null dilewatkan ke nilai di mana nol tidak diizinkan. Secara default, ini mengasumsikan tidak ada yang diizinkan menjadi nol kecuali jika dijelaskan demikian. Dengan cara ini, Anda tidak perlu khawatir tentang nilai nol. Melewati nilai nol ke parameter akan menghasilkan kesalahan kompiler. Menguji objek untuk null yang tidak bisa nol menghasilkan peringatan kompiler. Efeknya adalah mengubah NullPointerException dari kesalahan runtime menjadi kesalahan waktu kompilasi.
Ini mengubah segalanya.
Sedangkan untuk getter Anda, jangan gunakan Opsional. Dan cobalah untuk merancang kelas Anda sehingga tidak ada anggota yang bisa menjadi nol. Dan mungkin mencoba menambahkan Nullness Checker ke proyek Anda dan mendeklarasikan parameter getter dan setter Anda @Nullable jika mereka membutuhkannya. Saya hanya melakukan ini dengan proyek-proyek baru. Mungkin menghasilkan banyak peringatan dalam proyek yang ada ditulis dengan banyak tes berlebihan untuk null, jadi mungkin sulit untuk memperbaiki. Tetapi juga akan menangkap banyak bug. Aku menyukainya. Kode saya jauh lebih bersih dan lebih andal karenanya.
(Ada juga bahasa baru yang membahas hal ini. Kotlin, yang mengkompilasi ke kode byte Java, memungkinkan Anda untuk menentukan apakah suatu objek mungkin nol ketika Anda mendeklarasikannya. Ini adalah pendekatan yang lebih bersih.)
Tambahan untuk Posting Asli (versi 2)
Setelah memberikannya banyak pemikiran, saya dengan enggan sampai pada kesimpulan bahwa dapat diterima untuk kembali Opsional dengan satu syarat: Bahwa nilai yang diambil mungkin sebenarnya nol. Saya telah melihat banyak kode di mana orang-orang secara rutin mengembalikan Opsional dari getter yang tidak mungkin mengembalikan null. Saya melihat ini sebagai praktik pengkodean yang sangat buruk yang hanya menambah kompleksitas kode, yang membuat bug lebih mungkin. Tetapi ketika nilai yang dikembalikan mungkin benar-benar nol, lanjutkan dan bungkus dalam Opsional.
Perlu diingat bahwa metode yang dirancang untuk pemrograman fungsional, dan yang memerlukan referensi fungsi, akan (dan harus) ditulis dalam dua bentuk, salah satunya menggunakan Opsional. Sebagai contoh, Optional.map()
dan Optional.flatMap()
keduanya mengambil referensi fungsi. Yang pertama mengambil referensi ke pengambil biasa, dan yang kedua mengambil yang mengembalikan Opsional. Jadi, Anda tidak melakukan bantuan siapa pun dengan mengembalikan Opsional di mana nilainya tidak boleh nol.
Setelah mengatakan semua itu, saya masih melihat pendekatan yang digunakan oleh Nullness Checker adalah cara terbaik untuk menangani nulls, karena mereka mengubah NullPointerExceptions dari bug runtime untuk mengkompilasi kesalahan waktu.