Menu

Java Optional: null ve NullPointerException'dan kaçınma

java.util.Optional nedir, nasıl oluşturulur ve değeri null kontrolleri yerine map, filter, orElse ve ifPresent ile nasıl güvenli okunur.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Optional'ın çözdüğü sorun

Bir cevabı olmayabilecek bir metot Java'da her zaman rahatsız edici bir seçeneğe sahipti: null döndürüp çağıran tarafın kontrol etmeyi hatırlamasını ummak. Genellikle hatırlamazlar ve sonuç, null döndüren metottan çok uzakta ortaya çıkan bir NullPointerException olur.

Optional<T>, ya bir değer içeren ya da açıkça boş olan küçük bir kutudur. Bir metot User yerine Optional<User> döndürerek çağıran tarafa, kendi imzasında "bu hiçbir şey bulmayabilir" der - ve derleyici onları bu durumu ele almaya yönlendirir.

Bir Optional oluşturma

Üç fabrika metodu var ve doğru olanı seçmek önemli:

  • Optional.of(value) - değer null olmamalı, yoksa anında NullPointerException fırlatır.
  • Optional.ofNullable(value) - değer null ise boş, aksi halde dolu. Null olabilecek bir şeyi sarmalamak için bunu kullan.
  • Optional.empty() - boş bir optional.

Yaygın bir hata, null olabilecek bir değer için Optional.of(x)'e başvurmaktır - bu amacı baltalar ve tam da kaçınmaya çalıştığın istisnayı fırlatır. Şüphedeysen ofNullable kullan.

Değeri güvenli okuma

Bir optional'ın elinde olduğunda amaç, değerin orada olduğunu varsaymadan onu dışarı çıkarmaktır. Kaba araç get()'tir ve onu neredeyse hiç kullanmamalısın:

Optional<String> name = Optional.empty();
String value = name.get();   // NoSuchElementException fırlatır - kılık değiştirmiş NPE

Bunun yerine bir yedek değer sağla veya varlığa tepki ver. orElse boşken bir varsayılan döndürür; ifPresent yalnızca bir değer var olduğunda kod çalıştırır:

Varsayılanı oluşturmak pahalıysa orElse yerine orElseGet(supplier) kullan - supplier yalnızca optional gerçekten boşsa çalışır. orElse'in argümanı, gerekmese bile her zaman değerlendirilir.

"Bu var olmalı" için orElseThrow

Bazen boş olmak gerçekten bir hatadır - zorunlu bir yapılandırma değeri, veritabanında olması gereken bir kullanıcı. orElseThrow, boş bir optional'ı seçtiğin net bir istisnaya dönüştürür:

Bu, bir if (opt.isPresent()) bloğundan çok daha iyi okunur ve hatayı tam olduğu noktada açık hale getirir.

map ve filter ile dönüştürme

Asıl kazanç zincirlemededir. map, bir fonksiyonu değere yalnızca varsa uygular ve boş bir optional'ı boş bırakır - böylece bir null'a hiç dokunmadan dönüşüm yaparsın. filter, bir testi geçemezse değeri atar.

Eşleme fonksiyonunun kendisi bir Optional döndürüyorsa, rahatsız edici bir Optional<Optional<T>>'den kaçınmak için map yerine flatMap kullan. Bu, stream'lerde gördüğün map/flatMap ayrımını yansıtır - bir Optional, sıfır veya bir elemanlı bir stream gibi davranır.

Optional nereye ait (ve nereye değil)

Optional, meşru biçimde sonuç üretmeyebilecek metotlar için bir dönüş tipi olarak tasarlanmıştır - klasik örnekler Stream.findFirst(), Map tarzı aramalar ve ayrıştırmadır. Onu orada kullan, API'n kendi boşluklarını belgelemiş olur.

Şunlar için tasarlanmamıştır:

  • Alanlar. Serileştirilebilir değildir ve her alan için bir nesne ekler. Düz referanslar kullan ve yapıcıda doğrula.
  • Metot parametreleri. O zaman çağıran tarafın argümanları Optional.of(...) içine sarması gerekir ki bu, bir aşırı yükleme veya null kabul eden bir parametreden daha gürültülüdür.
  • Koleksiyonlar. Optional<List> değil, boş bir List döndür. Boş bir koleksiyon zaten "hiçbir şey" anlamına gelir.

Bir dönüş tipi olarak ele alındığında Optional, sessiz null hatalarını eksik durumu ele almaya yönelik derleme zamanı uyarılarına dönüştürür.

Sıradaki: İstisnalar

Optional, günlük "değer olmayabilir" durumunu temiz bir şekilde ele alır, ama bazı hatalar gerçekten istisnaidir - açılmayan bir dosya, kopan bir ağ, ayrıştırılamayan bir girdi. Java bunları istisnalarla modeller ve bu da bir sonraki sayfadır.

Sıkça Sorulan Sorular

Java'da Optional nedir ve neden kullanılır?

Optional<T>, ya bir değer tutan ya da boş olan bir kaptır. Bir metodun dönüş tipinde "değer olmayabilir" durumunu açıkça belirtmek için vardır; böylece çağıran taraf, bir null kontrolünü unutup çalışma zamanında NullPointerException ile karşılaşmak yerine boş durumu ele almaya yönlendirilir. Onu özellikle, hiçbir şey bulamayan bir arama gibi sonuç üretmeyebilecek metotların dönüş tipi olarak kullan.

Optional.of ile Optional.ofNullable arasındaki fark nedir?

Optional.of(x), x null ise hemen NullPointerException fırlatır - değerin null olmadığını bildiğinde kullan. Optional.ofNullable(x), x null olduğunda boş bir Optional, aksi halde dolu olanını döndürür - değerin null olabileceği durumlarda kullan. Optional.empty() sana doğrudan boş bir optional verir.

Değeri okumak için Optional.get() çağırmalı mıyım?

Doğrudan get() kullanmaktan kaçın - optional boşsa NoSuchElementException fırlatır ki bu sadece başka bir isim altındaki NullPointerException'dır. Boş durumun her zaman ele alınması için orElse, orElseGet, orElseThrow, ifPresent veya map tercih et. Önce kontrol etmen gerekiyorsa isPresent() ile koru, ama fonksiyonel metotlar daha temizdir.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA