JavaRush /Java blogi /Random-UZ /Kofe tanaffusi №161. Ixtiyoriy yordamida Java-da Null-ni ...

Kofe tanaffusi №161. Ixtiyoriy yordamida Java-da Null-ni qanday boshqarish kerak

Guruhda nashr etilgan
Manba: O'rta Ushbu maqola Java kodi bilan ishlashda ixtiyoriy maqsadini yaxshiroq tushunishga yordam beradi. Kofe tanaffusi №161.  Ixtiyoriy yordamida Java-da Null-ni qanday boshqarish mumkin - 1Java kodi bilan birinchi marta ishlay boshlaganimda, menga ko'pincha Optional dan foydalanishni maslahat berishardi. Ammo o'sha paytda men nega ixtiyoriy foydalanish null qiymatlar uchun ishlov berishni amalga oshirishdan ko'ra yaxshiroq ekanligini tushunmagan edim. Ushbu maqolada men nima uchun barchamiz Optional-dan ko'proq foydalanishimiz kerak deb o'ylayman va kod sifatiga zarar etkazadigan kodingizni ortiqcha opsiyalashdan qanday qochish kerakligini siz bilan baham ko'rmoqchiman.

Ixtiyoriy nima?

Majburiy emas parametr ob'ektlarni tashish va null havolalarni turli API-lar tomonidan ishlov berishni yoqish uchun ishlatiladi . Keling, kod parchasini ko'rib chiqaylik:
Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
Bizda Qahva namunasi mavjud bo'lib, unda biz Shakar ob'ektining bir nusxasidan qand miqdorini olamiz . Qahva konstruktorida miqdor qiymati hech qachon o'rnatilmagan deb hisoblasak , coffee.getSugar().getQuantity() NullPointerException ni qaytaradi . Albatta, biz muammoni hal qilish uchun har doim yaxshi eski null tekshiruvlaridan foydalanishimiz mumkin.
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
  quantity = coffee.getSugar().getQuantity();
}
Endi hammasi yaxshi bo'lganga o'xshaydi. Lekin Java kodini yozishda biz null tekshiruvlarini qo'llashdan qochgan ma'qul . Keling, buni Opsiyonel yordamida qanday qilish mumkinligini ko'rib chiqaylik.

Ixtiyoriyni qanday yaratish kerak

Ixtiyoriy ob'ektlarni yaratishning uchta usuli mavjud:
  • of(T qiymati) - ixtiyoriy null bo'lmagan ob'ektni yaratish. Shuni yodda tutingki, null ob'ektga murojaat qilish uchun of() dan foydalanish NullPointerException ni keltirib chiqaradi .

  • ofNullable(T qiymati) - null bo'lishi mumkin bo'lgan ob'ekt uchun ixtiyoriy qiymat yaratadi.

  • empty() - null ga havolani ifodalovchi ixtiyoriy misol yaratadi .

// пример использования 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();
Shunday qilib, sizda ixtiyoriy ob'ekt mavjud. Endi ixtiyoriy uchun ikkita asosiy usulni ko'rib chiqamiz:
  • isPresent() - Bu usul ixtiyoriy ob'ektda null bo'lmagan qiymat mavjudligini bildiradi.

  • get() - joriy qiymat bilan ixtiyoriy uchun qiymatni oladi. Shuni yodda tutingki, get() ni bo'sh ixtiyoriy qo'ng'iroq qilish NullPointerException ga olib keladi .

E'tibor bering, agar siz ixtiyoriy bilan ishlashda faqat get() va isPresent() dan foydalansangiz, siz buni o'tkazib yuborasiz! Buni tushunish uchun yuqoridagi misolni ixtiyoriy bilan qayta yozamiz.

Ixtiyoriy bilan Null tekshiruvini yaxshilash

Xo'sh, yuqoridagi kodni qanday yaxshilashimiz mumkin? Ixtiyoriy bilan biz isPresent() yordamida ob'ekt mavjudligini tushunishimiz va get() yordamida uni olishimiz mumkin . Keling, coffee.getSugar() natijasini ixtiyoriy bilan va isPresent() usuli yordamida qadoqlashdan boshlaylik . Bu getSugar() null qiymatini qaytaradimi yoki yo'qligini aniqlashga yordam beradi .
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();
}
Ushbu misolga nazar tashlaydigan bo'lsak, coffee.getSugar() natijasini ixtiyoriyga joylashtirish hech qanday qiymat qo'shmaydi, aksincha, qiyinchilik tug'diradi. Ixtiyoriy sinfdagi eng sevimli funksiyalarim deb hisoblaganimdan foydalanib, natijani yaxshilashimiz mumkin:
  • map(Function<? super T,? extensions U> mapper) - Majburiy bo'lmaganda mavjud bo'lgan qiymatni taqdim etilgan funksiyaga moslashtiradi. Agar ixtiyoriy parametr bo'sh bo'lsa, map() Optional.empty() ni qaytaradi .

  • orElse(T other) get() usulining “maxsus” versiyasidir . U ixtiyoriy tarkibidagi qiymatni olishi mumkin. Biroq, bo'sh ixtiyoriy bo'lsa, bu orElse() usuliga o'tkazilgan qiymatni qaytaradi .

Usul ixtiyoriy misoldagi qiymatni qaytaradi. Agar ixtiyoriy parametr bo'sh bo'lsa, ya'ni unda hech qanday qiymat yo'q bo'lsa, orElse() standart qiymat sifatida ma'lum bo'lgan metod imzosiga o'tkazilgan qiymatni qaytaradi.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
    .map(it -> it.getQuantity())
    .orElse(0);
Bu juda ajoyib - hech bo'lmaganda men shunday deb o'ylayman. Endi, agar bo'sh qiymat bo'lsa, biz standart qiymatni qaytarishni istamasak, unda qandaydir istisno qilishimiz kerak. orElseThrow(Supplier<? extensions X> exceptionSupplier) ixtiyoriy parametrlar tarkibidagi qiymatni qaytaradi yoki ixtiyoriy parametr boʻsh boʻlsa, istisno qiladi.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
  .map(it -> it.getQuantity())
  .orElseThrow(IllegalArgumentException::new);
Ko'rib turganingizdek, ixtiyoriy bir nechta afzalliklarni beradi:
  • null cheklarni abstrakt qiladi
  • null ob'ektlar bilan ishlash uchun API taqdim etadi
  • erishilayotgan narsalarni ifodalash uchun deklarativ yondashuvga imkon beradi

Ixtiyoriy bilan qanday samarali bo'lish mumkin

Mening ishimda, agar usul "natija yo'q" holatini qaytarishi mumkin bo'lsa, qaytarish turi sifatida Optional dan foydalanaman. Men odatda usullar uchun qaytarish turlarini belgilashda foydalanaman.
Optional<Coffee> findByName(String name) {
   ...
}
Ba'zan bu kerak emas. Misol uchun, agar menda Sugar sinfida getQuantity() kabi int ni qaytaradigan usul bo'lsa , natija null bo'lsa, "miqdori yo'q" ni ifodalash uchun usul 0 ni qaytarishi mumkin . Endi buni bilib, Coffee sinfidagi Shakar parametrini Opsiyonel sifatida ko'rsatish mumkin deb o'ylashimiz mumkin . Bir qarashda, bu yaxshi fikrga o'xshaydi, chunki nazariy jihatdan qahva tarkibida shakar bo'lishi shart emas. Biroq, men bu erda ixtiyoriy ishlatmaslik kerakligi haqida gaplashmoqchiman . Quyidagi stsenariylarda ixtiyoriy foydalanishdan qochishimiz kerak:
  • DTO'lar kabi POJO'lar uchun parametr turlari sifatida . Opsiyonellarni ketma-ketlashtirib bo'lmaydi, shuning uchun ularni POJOda ishlatish ob'ektning seriyali bo'lishini o'chiradi.

  • Usul argumenti sifatida. Agar usul argumenti null bo'lishi mumkin bo'lsa, sof kod nuqtai nazaridan, null ni o'tkazish ixtiyoriy o'tishdan ko'ra afzalroqdir. Bundan tashqari, null usul argumenti yo'qligini mavhum tarzda boshqarish uchun ortiqcha yuklangan usullarni yaratishingiz mumkin.

  • Yo'qolgan Collection ob'ektini ko'rsatish uchun. To'plamlar bo'sh bo'lishi mumkin, shuning uchun qiymatsiz To'plamni ko'rsatish uchun bo'sh To'plam yoki List kabi bo'sh To'plamdan foydalanish kerak.

Xulosa

Majburiy emas Java kutubxonasiga kuchli qo'shimcha bo'ldi. U mavjud bo'lmagan ob'ektlarni boshqarish usulini taqdim etadi. Shuning uchun, suiiste'mol tuzog'iga tushmasdan usullarni ishlab chiqishda e'tiborga olish kerak. Ha, siz null tekshiruvlar va null ishlov berishni amalga oshiradigan ajoyib kod yozishingiz mumkin, ammo Java hamjamiyati ixtiyoriy foydalanishni afzal ko'radi. U etishmayotgan qiymatlarni qanday boshqarishni samarali tushuntiradi, tartibsiz Null tekshiruvlariga qaraganda o'qish ancha oson va uzoq muddatda kodingizda kamroq xatolarga olib keladi.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION