Her Java geliştiricisi NullPointerException istisnalarıyla uğraşmıştır. null değer ile karşılaşmak, ona karşı önlem almak herzaman için can sıkıcı olmuştur. Bu can sıkıcılığını ortadan kaldırmak için Java 8 ile beraber Optional sınıfı gelmiştir. Optional yapısı daha evvelden farklı dillerde bulunan bir özelliktir.
Optional türünden nesneler, null olma ihtimali olan nesneleri kolay yönetmek için oluşturulmuştur.
Varsayalım ki, verilen kullanıcı adına göre veri listemizde kullanıcıyı bulan bir metodumuz olsun.
1 |
Public User findUserByName(String userName) { ... }; |
Bu metodu çağıran sınıfımızda şu şekilde olsun
1 2 |
User user = findUserByName("Koray"); System.out.println("Kullanıcı Adı = " + user.getName()); |
Eğer ” Koray ” adında bir kullanıcımız yoksa burada null olan user nesnesinin getName metodunu çağırdığımızda NullPointerException fırlatacak ve program kırılacaktır.
Şimdi aynı senaryo üzerinden Optional kullanarak NullPointerException’dan nasıl kaçınacağız görelim.
User sınıfı :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
package java8.optional; public class User { private Long id; private String userName; private String name; public User(Long id, String userName, String name) { this.id = id; this.userName = userName; this.name = name; } public Long getId() { return id; } public String getName() { return name; } public String getUserName() { return userName; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (id != null ? !id.equals(user.id) : user.id != null) return false; return name != null ? name.equals(user.name) : user.name == null; } @Override public int hashCode() { int result = id != null ? id.hashCode() : 0; result = 31 * result + (name != null ? name.hashCode() : 0); return result; } } |
UserDao sınıfı :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
package java8.optional; import java.util.ArrayList; import java.util.List; public class UserDao { private List<> userList; public UserDao() { getUsers(); } private void getUsers(){ userList = new ArrayList<>(); User user1 = new User(1L, "kry1453", "Koray"); User user2 = new User(2L, "koray123", "Koray"); User user3 = new User(3L, "korAy987", "Koray"); User user4 = new User(4L, "hltcn", "Halit"); User user5 = new User(5L, "tnr", "Taner"); userList.add(user1); userList.add(user2); userList.add(user3); userList.add(user4); userList.add(user5); } public User findUserByUserName(String userName){ User user = null; for (User eachUser : userList) { if(eachUser.getUserName().equals(userName)){ user = eachUser; } } return user; } public void deleteUser(User user){ userList.remove(user); System.out.print(user.getUserName() + " kullanıcısı silindi. Diğer Kullanıcılar : "); userList.stream().forEach(value -> System.out.print(" " + value.getUserName())); System.out.println(); } } |
Optional Nesnesi Nasıl Oluşturulur
Üç şekilde Optional nesnesi oluşturabiliriz. Kullanıcının adına göre kullanıcımızı çekip optional oluşturma işlemlerine başlayalım.
1 |
User user = userDao.findUserByUserName("kry1453"); |
- Boş optional nesnesi oluştururak
1 |
Optional optional1 = Optional.empty(); |
- Null olmayan değer ile optional nesnesi oluşturarak
Optional.of () öğesine gönderilen değer null ise , NullPointerException’ı hemen fırlatır ve Optional nesnesi oluşturulmaz.
1 |
Optional optional2 = Optional.of(user); |
- Null olabilecek veya olmayabilecek bir değer ile optional nesnesi oluşturarak
1 |
Optional optional3 = Optional.ofNullable(user); |
Optional Kullanımları
get()
Optional içerisindeki değeri verir. Dikkat edilmesi gereken husus bu metodu kesinlikle ve kesinlike optional içerisinde değer varsa kullanılmalıdır yoksa NoSuchElementException fırlaması kaçınılmazdır. Bu sebeple en azından isPresent metodu ile kontrol edip akabinde çağırmak en mantıklısıdır.
isPresent (Var mı ?)
Present kelime anlamı olarak da mevcut olduğundan mevcut mu diye kontrol eder. Eğer optional içerisinde değer null değilse true döndürür diğer durumlarda false döndürür.
1 2 3 |
System.out.println("Optinal1 : " + optional1.isPresent()); System.out.println("Optinal2 : " + optional2.isPresent()); System.out.println("Optinal3 : " + optional3.isPresent()); |
ifPresent (Varsa yap)
Eğer bir Optional içerisinde değer varsa (null değilse) bir işin yapılması isteniyorsa ifPresent metodu kullanılabilir. ifPresent metodu Consumer fonksiyonel arayüzü türünden bir nesne kabul etmektedir.
1 2 3 |
optional3.ifPresent(value -> { userDao.deleteUser(value); }); |
map (Dönüştürme)
Optional nesnelerinin sarmaladığı veriler üzerinde dönüşüm yapar.
1 2 |
optional3.map(value -> value.getUserName().length()).ifPresent(System.out::println); optional1.map(value -> value.getUserName().length()).ifPresent(System.out::println); |
filter (Filtreleme)
Optional nesnelerinin sarmaladığı veriler üzerinde süzme işlemi de yapılabilmektedir.
1 2 3 |
optional3.filter(value -> value.getName().equals("Kray")).ifPresent(value -> { userDao.deleteUser(value); }); |
orElse (Varsa al, yoksa bunu al)
orElse metodu daha çok ternary (üçlü) şart ihtiyacı olduğu durumlarda ihtiyaç duyulabilir. Daha akıcı bir geliştirim deneyimi sunar.
1 2 3 4 5 |
User userHalitCan = userDao.findUserByUserName("hltcn"); User user1 = optional1.orElse(userHalitCan); User user2 = optional3.orElse(userHalitCan); System.out.println("orElse örneği optional1 Kullanıcı " + user1.getUserName()); System.out.println("orElse örneği optioanel3 Kullanıcı " + user2.getUserName()); |
orElseGet (Varsa al, yoksa üret)
Bu metod orElse metoduna çok benzer, fakat orElseGet metod parametresi olarak Supplier fonksiyonel arayüzü türünden nesne kabul eder.
1 2 3 4 |
User user3 = optional1.orElseGet(() -> userDao.findUserByUserName("hltcn")); User user4 = optional3.orElseGet(() -> userDao.findUserByUserName("hltcn")); System.out.println("orElseGet örneği optional1 Kullanıcı " + user3.getUserName()); System.out.println("orElseGet örneği optional3 Kullanıcı " + user4.getUserName()); |
orElseThrow (Varsa al, yoksa exception fırlat)
Optional nesnesi bir değeri içeriyorsa (null olmayan) o değeri döndürür, null ise de sağlanan istisna nesnesini fırlatır. orElseThrow metodu Supplier türünden bir nesne kabul eder.
1 2 3 4 5 6 |
optional3.orElseThrow(NullPointerException::new); try { optional1.orElseThrow(NullPointerException::new); } catch (NullPointerException e){ System.out.println("orElseThrow örneği optional1 throw exception"); } |
Optional’ın özellikleri bu kadar. Tüm özellikleri çağıran kodun tamamı şu şekildedir. Kendi bilgisayarınızda deneyerek daha çabuk öğreneceğinizden eminim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
package java8.optional; import java.util.Optional; public class OptionalTester { static UserDao userDao = new UserDao(); public static void main(String[] args) { User user = userDao.findUserByUserName("kry1453"); // Optional oluşturma Optional optional1 = Optional.empty(); Optional optional2 = Optional.of(user); Optional optional3 = Optional.ofNullable(user); // isPresent System.out.println("Optinal1 : " + optional1.isPresent()); System.out.println("Optinal2 : " + optional2.isPresent()); System.out.println("Optinal3 : " + optional3.isPresent()); // ifPresent optional3.ifPresent(value -> { userDao.deleteUser(value); }); // map System.out.println("map örneği"); optional3.map(value -> value.getUserName().length()).ifPresent(System.out::println); optional1.map(value -> value.getUserName().length()).ifPresent(System.out::println); // filter System.out.println("filter örneği"); optional3.filter(value -> value.getName().equals("Kray")).ifPresent(value -> { userDao.deleteUser(value); }); // orElse User userHalitCan = userDao.findUserByUserName("hltcn"); User user1 = optional1.orElse(userHalitCan); User user2 = optional3.orElse(userHalitCan); System.out.println("orElse örneği optional1 Kullanıcı " + user1.getUserName()); System.out.println("orElse örneği optioanel3 Kullanıcı " + user2.getUserName()); // orElseGet User user3 = optional1.orElseGet(() -> userDao.findUserByUserName("hltcn")); User user4 = optional3.orElseGet(() -> userDao.findUserByUserName("hltcn")); System.out.println("orElseGet örneği optional1 Kullanıcı " + user3.getUserName()); System.out.println("orElseGet örneği optional3 Kullanıcı " + user4.getUserName()); // orElseThrow optional3.orElseThrow(NullPointerException::new); try { optional1.orElseThrow(NullPointerException::new); } catch (NullPointerException e){ System.out.println("orElseThrow örneği optional1 throw exception"); } } } |
Java8 ile gelen yenilikler arasında öğrenilmesi gereken şeylerden birisi. Bu güzel, aydınlatıcı ve örneklerle dolu yazı için teşekkürler hocam 🙂