JavaRush /Blog Java /Random-MS /Coffee break #161. Bagaimana untuk mengendalikan Null di ...

Coffee break #161. Bagaimana untuk mengendalikan Null di Java menggunakan Pilihan

Diterbitkan dalam kumpulan
Sumber: Sederhana Artikel ini akan membantu anda memahami dengan lebih baik tujuan Pilihan apabila bekerja dengan kod Java. Coffee break #161.  Bagaimana untuk mengendalikan Null di Java menggunakan Pilihan - 1Apabila saya mula bekerja dengan kod Java, saya sering dinasihatkan untuk menggunakan Pilihan. Tetapi pada masa itu saya kurang memahami mengapa menggunakan Pilihan adalah lebih baik daripada melaksanakan pengendalian untuk nilai nol. Dalam artikel ini, saya ingin berkongsi dengan anda mengapa saya fikir kita semua harus menggunakan Opsional lebih banyak, dan cara untuk mengelakkan terlalu memilih kod anda, yang memudaratkan kualiti kod.

Apakah Pilihan?

Parameter Pilihan digunakan untuk membawa objek dan membolehkan rujukan nol dikendalikan oleh pelbagai API. Mari lihat coretan kod:
Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
Kami mempunyai contoh Kopi di mana kami mendapat sedikit gula daripada contoh objek Gula . Jika kita menganggap bahawa nilai kuantiti tidak pernah ditetapkan dalam Coffee constructor , maka coffee.getSugar().getQuantity() akan mengembalikan NullPointerException . Sudah tentu, kita sentiasa boleh menggunakan semakan nol lama yang baik untuk menyelesaikan masalah.
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
  quantity = coffee.getSugar().getQuantity();
}
Sekarang semuanya kelihatan baik-baik saja. Tetapi apabila menulis kod Java, lebih baik kita mengelak daripada melaksanakan semakan nol . Mari lihat bagaimana ini boleh dilakukan menggunakan Pilihan.

Bagaimana untuk membuat Pilihan

Terdapat tiga cara untuk mencipta objek Pilihan:
  • of(T value) — instantiasi objek bukan nol Pilihan. Sedar bahawa menggunakan of() untuk merujuk kepada objek null akan membuang NullPointerException .

  • ofNullable(T value) - mencipta nilai Pilihan untuk objek yang boleh menjadi null.

  • empty() - Mencipta contoh Pilihan yang mewakili rujukan kepada null .

// пример использования Optional.of(T Value)
String name = "foo";
Optional<String> stringExample = Optional.of(name)
// пример использования Optional.ofNullable(T Value)
Integer age = null;
Optional<Integer> integerExample= Optional.ofNullable(age)
// пример использования Optional.empty()
Optional<Object> emptyExample = Optional.empty();
Jadi anda mempunyai objek Pilihan. Sekarang mari kita lihat dua kaedah utama untuk Pilihan:
  • isPresent() - Kaedah ini memberitahu anda sama ada objek Pilihan mengandungi nilai bukan nol.

  • get() - Mendapatkan nilai untuk Pilihan dengan nilai semasa. Harap maklum bahawa memanggil get() pada Optional kosong akan menghasilkan NullPointerException .

Sila ambil perhatian bahawa jika anda hanya menggunakan get() dan isPresent() apabila bekerja dengan Optional, anda akan terlepas! Untuk memahami perkara ini, mari kita tulis semula contoh di atas dengan Pilihan.

Memperbaik Pemeriksaan Null dengan Pilihan

Jadi bagaimana kita boleh menambah baik kod di atas? Dengan Pilihan kita boleh memahami kehadiran objek menggunakan isPresent() dan mendapatkannya menggunakan get() . Mari kita mulakan dengan membungkus hasil coffee.getSugar() dengan Pilihan dan menggunakan kaedah isPresent() . Ini akan membantu kami menentukan sama ada getSugar() mengembalikan null.
Coffee coffee = new Coffee();
Optional<String> sugar = Optional.ofNullable(coffee.getSugar());
int quantity = 0;
if (sugar.isPresent()) {
  Sugar sugar = sugar.get();
  int quantity = sugar.getQuantity();
}
Melihat contoh ini, membungkus hasil coffee.getSugar() ke dalam Pilihan nampaknya tidak menambah apa-apa nilai, sebaliknya menambah kerumitan. Kami boleh menambah baik hasilnya dengan menggunakan apa yang saya anggap sebagai fungsi kegemaran saya daripada kelas Pilihan:
  • map(Function<? super T,? extends U> mapper) - Petakan nilai yang terkandung dalam Pilihan kepada fungsi yang disediakan. Jika parameter Pilihan kosong, maka map() akan mengembalikan Optional.empty() .

  • orElse(T other) ialah versi "istimewa" kaedah get() . Ia boleh mendapatkan nilai yang terkandung dalam Pilihan. Walau bagaimanapun, dalam kes Pilihan kosong, ini akan mengembalikan nilai yang dihantar kepada kaedah orElse() .

Kaedah ini akan mengembalikan nilai yang terkandung dalam contoh Pilihan. Tetapi jika parameter Pilihan kosong, bermakna ia tidak mengandungi nilai, maka orElse() akan mengembalikan nilai yang dihantar kepada tandatangan kaedahnya, yang dikenali sebagai nilai lalai.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
    .map(it -> it.getQuantity())
    .orElse(0);
Ini sangat keren - sekurang-kurangnya saya fikir begitu. Sekarang, jika dalam kes nilai kosong kita tidak mahu mengembalikan nilai lalai, maka kita perlu membuang beberapa jenis pengecualian. orElseThrow(Supplier<? extends X> exceptionSupplier) mengembalikan nilai yang terkandung dalam parameter Pilihan, atau membuang pengecualian jika Pilihan kosong.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
  .map(it -> it.getQuantity())
  .orElseThrow(IllegalArgumentException::new);
Seperti yang anda lihat, Pilihan memberikan beberapa kelebihan:
  • abstrak semakan nol
  • menyediakan API untuk mengendalikan objek nol
  • membolehkan pendekatan deklaratif untuk menyatakan apa yang dicapai

Bagaimana untuk menjadi berkesan dengan Pilihan

Dalam kerja saya, saya menggunakan Pilihan sebagai jenis pulangan apabila kaedah boleh mengembalikan keadaan "tiada hasil". Saya biasanya menggunakannya apabila menentukan jenis pulangan untuk kaedah.
Optional<Coffee> findByName(String name) {
   ...
}
Kadang-kadang ini tidak perlu. Sebagai contoh, jika saya mempunyai kaedah yang mengembalikan int , seperti getQuantity() dalam kelas Sugar , maka kaedah itu mungkin mengembalikan 0 jika hasilnya nol untuk mewakili "tiada kuantiti". Sekarang, mengetahui perkara ini, kita boleh berfikir bahawa parameter Gula dalam kelas Kopi boleh diwakili sebagai Pilihan. Pada pandangan pertama, ini kelihatan seperti idea yang baik kerana, secara teori, gula tidak perlu ada dalam kopi. Walau bagaimanapun, di sinilah saya ingin menangani apabila tidak menggunakan Pilihan. Kita harus mengelak daripada menggunakan Pilihan dalam senario berikut:
  • Sebagai jenis parameter untuk POJO , seperti DTO . Pilihan tidak boleh bersiri, jadi menggunakannya dalam POJO menjadikan objek tidak boleh bersiri.

  • Sebagai hujah kaedah. Jika argumen kaedah boleh menjadi null , maka dari perspektif kod tulen, lulus null masih lebih baik daripada lulus Pilihan. Selain itu, anda boleh mencipta kaedah terlebih beban untuk mengendalikan ketiadaan hujah kaedah nol secara abstrak.

  • Untuk mewakili objek Koleksi yang tiada. Koleksi boleh kosong, jadi Koleksi kosong , seperti Set atau Senarai kosong , mesti digunakan untuk mewakili Koleksi tanpa nilai.

Kesimpulan

Pilihan telah menjadi tambahan yang hebat kepada perpustakaan Java. Ia menyediakan cara untuk mengendalikan objek yang mungkin tidak wujud. Oleh itu, ia harus diambil kira apabila membangunkan kaedah tanpa jatuh ke dalam perangkap penyalahgunaan. Ya, anda boleh menulis kod hebat yang melaksanakan semakan nol dan pengendalian null, tetapi komuniti Java lebih suka menggunakan Pilihan. Ia secara berkesan menyampaikan cara mengendalikan nilai yang hilang, lebih mudah dibaca daripada semakan Null yang tidak kemas, dan menghasilkan lebih sedikit pepijat dalam kod anda dalam jangka masa panjang.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION