ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java8. Optional
    BackEnd/Java 2022. 1. 22. 08:13
    반응형

      Optional은 비어있을 수도 있고, 오직 값 한개가 들어있을 수도 있는 컨테이너 인스턴스입니다. 메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드 타입으로도 사용이 가능하지만 리턴값으로만 사용하도록 권장합니다. 프리미티브 타입용 Optional(OptionalInt, OptionalLong 등)은 따로 존재하며, Collection, Map, Stream, Array, Optional은 자체적으로 비어있는 것을 확인할 수 있기 때문에 Optional로 감싸지 않습니다.

     

      Person과 Info 도메인이 존재할 때 아래와 같이 호출을 하게 되면 NullPointerException이 발생합니다.

    public class Person {
      private int age;
      private String name;
      private Info info;
    
      public Person(int age, String name) {
        this.age = age;
        this.name = name;
      }
    
      public String getName() {
        return name;
      }
    
      public void setName(String name) {
        this.name = name;
      }
    
      public Info getInfo() {
        return info;
      }
    
      public void setInfo(Info info) {
        this.info = info;
      }
    }
    public class Info {
      private int height;
    
      public int getHeight() {
        return height;
      }
    
      public void setHeight(int height) {
        this.height = height;
      }
    }
    public class OptionalClass {
    
      public static void main(String[] args) {
        Person person = new Person(6, "Daol");
        Info info = person.getInfo();
        System.out.println(info.getHeight());
    /*
        [결과]
        Exception in thread "main" java.lang.NullPointerException
          at OptionalClass.main(OptionalClass.java:6)
    */
      }
    
    }

      이러한 문제를 해결하기 위해 if(info != null) System.out.println(info.getHeight()); 같이 적용할 수 있지만 누락할 가능성이 존재합니다. Optional을 적용한 코드는 아래와 같습니다.

    import java.util.Optional;
    
    public class Person {
    
      ... 생략 ...
    
      public Optional<Info> getInfo() {
        return Optional.ofNullable(info);
      }
    
      ... 생략 ...
    }
    import java.util.Optional;
    
    public class OptionalClass {
    
      public static void main(String[] args) {
        Person person = new Person(6, "Daol");
        Optional<Info> info = person.getInfo();
        info.ifPresent(i -> System.out.println(i.getHeight()));
      }
    
    }

     

    Optional API

    • Optional 만들기: Optional.of() / Optional.ofNullable() / Optional.empty()
    • Optional 값 존재여부 확인: isPresent() / isEmpty() (Java 11부터 제공)
    • Optional에 있는 값 가져오기: get() / ifPresent(Consumer) / orElse(T) / orElseGet(Supplier) / orElseThrow()
    • Optional 필터링: Optional filter(Predicate)
    • Optional 변환: Optional map(Function) /
                              Optional flatMap(Function): Optional 안에 들어있는 인스턴스가 Optional인 경우 사용

      아래 샘플코드를 참고하여 사용하면 됩니다.

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;
    
    public class OptionalClass {
    
      public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person(6, "Daol"));
        list.add(new Person(4, "Iden"));
        list.add(new Person(3, "Jena"));
    
        // 이름에 "a"가 포함된 첫번째를 찾습니다.
        Optional<Person> optional = list.stream()
            .filter(l -> l.getName().contains("a"))
            .findFirst();
    /*
        System.out.println(optional.get().getName()); // [결과]: Daol (단, 값이 없는 경우 NoSuchElementException)
    */
        // 값이 있는 경우만 출력합니다.
        optional.ifPresent(o -> System.out.println(o.getName()));
    
        // 값이 존재하는지 확인합니다.
        boolean present = optional.isPresent();
        System.out.println(present); // [결과]: true
    
        // Optional에 값이 있으면 가져오고 없는 경우 새로운 인스턴스를 만듭니다.
        Person person = optional.orElseGet(OptionalClass::createNew);
        System.out.println(person.getName()); // [결과]: Daol
    
        // Optional에 값이 있으면 가져오고 없는 경우 에러를 던집니다.
        Person optionalThrow = optional.orElseThrow();
    
        // "A"로 시작하는 이름으로 필터링 합니다.
        Optional<Person> optionalFilter = optional
            .filter(l -> l.getName().startsWith("A"));
        System.out.println(optionalFilter.isEmpty()); // [결과]: true
        
        // 이름에 성을 붙여 새로운 Optional을 만듭니다.
        Optional<String> newOptional = optional.map(o -> o.getName() + " Kim");
        newOptional.ifPresent(System.out::println); // [결과]: Daol Kim
      }
    
      private static Person createNew() {
        return new Person(35, "Hanseom");
      }
    
    }

     

    반응형

    댓글

Designed by Tistory.