JAVA

JAVA - Optional 사용하기

pows1011 2023. 3. 30. 13:53

Optional 객체 생성

  • Optional의 객체생성 방법은 Optional.of , Optional.ofNullable() , empty() , stream()의 종료연산으로 생성이 가능하다.

 

Optional.of

 

  • Null을 허용하지 않는다. ( NPE발생 )
  • 어쩌다 Null이 들어갈 수도 있다면, Option.ofNullable()을 사용해야 한다.
public static void of(String[] args) {
    Optional<String> opStr1 = Optional.of("111");
    Optional<String> opStr2 = Optional.of(null); // NullPointerException
}

 

Optional.ofNullable()

 

  • 이름처럼 Value가 Null인 경우에도 NPE를 발생시키지 않고 Empty객체로 초기화 된다.
public static void ofNullable(String[] args) {
    Optional<String> opStr3 = Optional.ofNullable("111");
    Optional<String> opStr4 = Optional.ofNullable(null);
}

 

empty()

 

  • Optinal의 Value값이 Null인 Optinal이다. Optional을 초기화할 때는 직접 null로 초기화 하는것 보다. empty() 객체를 참조하도록 하는것이 바람직하다. ( empty는 제네릭 메소드로 Optinal.value의 타입을 지정 할 수있다. )
  • Null을 대입해버리면 의미를 갖지 못한채 NPE를 야기할 수 있지만. empty()를 사용하며 이것으로 '없음'을  나타낼 수있기 때문.
public static void empty(String[] args) {
    Optional<String> opStr5 = Optional.<String>empty();
}

 

 

Optional의 Value 가져오는법

  • Optional에 담긴 Value를 가져올 땐 get(),orElse(),orElseGet()을 사용한다.  

 

get()

 

  • get()은 Value 값 자체를 반환하고, Null일 경우에는 NoSuchElementException을 발생시킨다. 그래서 사용을 권장하지 않는 방식이다.
  • 이를 대비할 수 있는 방법이 orElse()와 orElseGet()이다
  •  
public static void main(String[] args) {
    List < String > list = new ArrayList < > ();
    list.add("c");
    list.add("b");
    Optional < String > op1 = list.stream().findFirst();
    System.out.println(op1.get());

    Optional < String > op3 = Optional.ofNullable(null);
    //op3는 null이므로 NoSuchElementException 발생
    System.out.println(op3.get());
}
결과
c
NoSuchElementException

 

orElse()

 

  • Optional객체가 null이 아니면 값을 가져오고 null이면 Optional의 인자 타입이랑 같은 타입을 반환하게 할 수 있다.
public static void main(String[] args) {
    Optional < String > op1 = Optional.ofNullable("test");
    //Null이 아니므로 test출력
    System.out.println(op1.orElse("orElse"));
    
    Optional < String > op2 = Optional.ofNullable(null);
    //Null이므로 else출력
    System.out.println(op2.orElse("orElse"));
}
결과
test
orElse

 

orElseGet()

 

  • orElseGet는 orElse와 비슷하지만 인자로 Supplier를 받아 람다식으로 타입 인자를 반환할 수 있다.
public static void main(String[] args) {
    Optional < String > op1 = Optional.ofNullable(null);
    //Null이므로 else get을 출력
    System.out.println(op1.orElseGet(() - > {
        return "elseGet";
    }));
}
결과
elseGet

 

orElseThrow()

 

  • NoSuchElemetntException 외에도 지정한 예외를 발생시킨다.
public static void main(String[] args) {
    Optional < String > op1 = Optional.ofNullable(null);
    op1.orElseThrow();
}
결과
NoSuchElementException

 

 

Optional Value의 처리&가공

  • Optional 객체에도 Stream에서처럼 filter(),map(),flatMap()이 구현되어있다. Stream과의 사용이 똑같다.

 

filter()

 

  • filter의 predicate가 true이면 그대로 타입 객체를 포함한 Optional이 반환되고 false이면 NullOptional이 반환된다.
public static void main(String[] args) {
    Optional < String > op2 = Optional.ofNullable("a");
    //s.equals("a")는 true이므로 "a"를 포함한 optional객체 반환
    System.out.println(op2.filter(s - > s.equals("a")).get());

    Optional < String > op1 = Optional.ofNullable("a");
    //false이므로 null Optional객체 반환
    System.out.println(op1.filter(s - > s.equals("b")).get());
}
결과
a
NoSuchElementException

 

map()

 

  • Optional 객체의 값에 어떤 수정을 가해서 다른 값으로 변환시키는 메서드
// xyz -> 소문자로 변환
Optional.of("XYZ").map(String::toLowerCase).orElse("Not AB");

 

 

Optional Value가 Null일 경우에 대한 처리

  • isPresent() , ifPresent() , ifPresentOrElse()
  • Null인 경우를 확인하거나 Null인 경우를 처리할 로직을 정할 수 있다.

 

isPresent()

 

  • isPresent()는 Optional 객체의 값이 Null인지 여부, 즉 값이 존재하는지 여부만 판단해주는 용도다.
  •  
Optional.of("TEST").isPresent(); // true
Optional.of("TEST").filter(v -> "Not Equals".equals(v)).isPresent(); // false

 

ifPresent()

 

  • ifPresent(Consumer<T> action)은 null이 아닐 경우에만 action을 실행한다.
  • ifPresent()는 람다식을 인자로 받아, 값이 존재할 때 그 값에 람다식을 적용해준다. 만약 Optional 객체에 값이 없다면 람다식이 실행되지 않는다.
// TEST 출력
Optional.of("TEST").ifPresent(System.out::println);

// 아무것도 출력되지 않음
Optional.ofNullable(null).ifPresent(System.out::println);

 

 

ifPresentOrElse()

 

  • ifPresentOrElse(Consumer action, Runnable emptyAction)는 value가 null인 경우 처리할 로직과 null이 아닌 경우 처리할 로직을 모두 넘길 수 있다.
  • 최종적으로 값을 반환하는 메소드로 , ifPresent()와 유사하지만 인자를 하나더 받는다. 첫번째 인자로 받은 람다식은 Optional 객체에 값이 존재하는 경우에 실행되고, 두번째 인자로 받은 람다식은 Optional객체가 비어있을때 실행된다.