Java 8 Optional Nedir

Her java programcısı NullPointerException istisnasıyla sorun yaşamıştır. Nesnelere herhangi bir atama yapılmadan kullanılmaya çalışıldığı durumlarda fırlatılan istisnadır. Bir RuntimeException (çalışma zamanı istisnası) olduğu için program çalışmadan farkedilmezler. Bu durumla başa çıkılabilmesi için Java 8 de Optional<T> veri tipi tanıtıldı. Diğer dillerde önceden buna farklı isimde aynı işi yapan türler vardı.

Örnek bir NullPointerException durumu:

User user = userRepository.findById(3245);
System.out.println(String.format("Kullanıcı adı: %s", user.getName()));

Yukarıdaki örnekte verilen ID’ye sahip kullanıcı yoksa user nesnesi null olacağı için getName fonksiyonu çağırıldığı zaman Java malum istisnayı fırlatır.

Şimdi Optional kullanarak nasıl bu sorunu çözebileceğimize bakalım.

Optional<User> findById(Long id) { ... };
Optional<User> user = userRepository.findById(3245);

user.ifPresent(user -> {
    System.out.println(String.format("Kullanıcı adı: %s", user.getName()));
});

Böylelikle user nesnesini kullanmak isteyen kişi mecbur kontrol yapmak zorunda kalıyor.

Optional nesnesi oluşturma

  1. Boş bir Optional oluşturmak için
    Optional<User> user = Optional.empty();
    
  2. Boş olmayan bir Optional oluşturmak için
    User user = new User(3245, "Sedat");
    Optional<User> userOptional = Optional.of(user);
    

    Eğer user nesnesi null olarak verilirse hemen NullPointerException oluşur. Yani bir yerde kullanmaya kalmadan sorun ortaya çıkar.

  3. Null olan veya olmayan bir nesne ile Optional oluşturmak için
    Optional<User> userOptional = Optional.ofNullable(user);
    

    Eğer user nesnesi null ise boş bir Optional nesnesi döner.

Nesnenin varlığını kontrol etmek

  1. isPresent()
    Optional null olmayan bir değere sahipse true değeri döner.
    if (optional.isPresent()) {
     System.out.println("Değer : " + optional.get());
    } else {
     System.out.println("Değer bulunamadı");
    }
    
  2. ifPresent()
    Eğer bir değere sahipse değer aşağıdaki şekilde alınıp işlem yapılabilir. Ancak bir değere sahip değilse hiç birşey yapılmaz.
    optional.ifPresent(value -> {
     System.out.println("Değer bulundu: " + value);
    });
    

get() metodu kullanılarak nesnenin değeri alınabilir. Ancak null ise NoSuchElementException istisnası fırlatılır.

User user = optional.get();

Varsayılan değer döndürmek orElse()

Nesne boş ise varsayılan bir değer döndürmek istenilebilir. Önceki hali:

User newUser = (user != null) ? user : new User(1, "İsim");

orElse kullanarak:

User newUser = optionalUser.orElse(new User(1, "İsim"));

Varsayılan değer döndürmek orElseGet()

Nesne boş ise bazı işlemler yapıldıktan sonra bir varsayılan değer döndürmek için kullanılır.

User user = optionalUser.orElseGet(() -> {
    return new User(1, "İsim");
});

Boş değer durumunda istisna fırlatmak orElseThrow()

User user = userRepository.findById(12).orElseThrow(
    () -> new NotFoundUserException("Hata Mesajı");
);

Değerleri filtrelemek filter()

Nesnenin değeri kontrol edilmek istenebilir.

Önceki kullanım:

if (user != null && user.getYas() > 18) {
    System.out.println("Kullanıcı reşit");
}

Önce nesnenin boş olup olamadığını kontrol ediyoruz. Boş bir değer kontrol edilmez ise getYas() metodu çağırıldığında istisna oluşarak işlem yarıda kesilir.

Optional kullanarak:

userOptional.filter(user -> user.getYas() > 18).ifPresent(() -> {
    System.out.println("Kullanıcı reşit");
});