[JAVA]Optional이란?

ryudjae
|2021. 6. 17. 14:30
728x90

➡️Optional이란?

  • Java8에서 Optional<T>클래스를 사용해  NPE(NullPointException)을 방지할 수 있도록 도와준다.Optional<T>는 null이 올 수 있는 값을 감싸는 Wrapper 클래스로, 참조하더라도 NPE가 발생하지 않도록 도와준다. Optional 클래스는 value에 값을 저장하기 때문에  value가 null이어도 NPE를 발생시키기 않는다.

 


➡️NPE(NullPointException)

 우리가 개발을 할때 가장 많이 발생하고 힘들게하는 예외 중 하나가 NPE(NullPointException)이다. NPE(NullPointException)를 발생시키지 않을려면 null을 검증하는 로직을 추가 해야 하는데 , null을 검증해야하는 변수가 많으면 많을수록 코드가 지저분해지고 로직이 번거로워진다.그래서 null대신 초기값을 사용하기를 권장하기도 한다.

 

➡️Optional  객체 생성

>Optional.of : value가 null인 경우 NPE예외를 던진다. 반드시 값이 있어야 하는 객체인 경우 해당 메서드를 사용하면 된다.

>Optional.ofNullable : value가 null 인 경우 비어있는 Optional을 반환한다. 값이 null일수도 있는 것은 해당 메서드를 사용하면 된다.

 

>Optional.empty : 비어있는 Optional객체를 생성한다. 조건에 따라 분기를 태워야하고 반환할 값이 없는 경우에도 사용된다.

 

➡️Optional 중간처리 

:Optional 객체를 생성 한 후 사용가능한 메서드이다. 해당 메서드들은 다시 옵셔널을 반환하므로 메서드 체이닝을 통해 원하는 로직을 반복 삽입할 수 있습니다.

 

>filter

:predicate(반환값) 값이 참이면 해당 필터를 통과시키고 거짓이면 통과를 하지 못한다.

1
2
3
4
5
6
// 메서드 시그니처
public Optional<T> filter(Predicate<super T> predicate);
// 예제
Optional.of("True").filter((val) -> "True".eqauls(val)).orElse("NO DATA"); // "True"
Optional.of("False").filter((val) -> "True".eqauls(val)).orElse("NO DATA"); // "NO DATA"
 
cs

 

>map

: mapper 함수를 통해 입력값을 다른 값으로 변환하는 메서드이다.

1
2
3
public<U> Optional<U> map(Function<super T, ? extends U> mapper);
// 예제
Integer test = Optional.of("1").map(Integer::valueOf).orElseThrow(NoSuchElementException::new); // string to integer
cs

 

>flatMap

:mapper 함수를 통해 입력값을 다른 값으로 변환하는 메서드이다. map()메서드와 다른점은 메서드 시그니처의 매개변수입니다.

1
2
3
4
5
6
7
// 메서드 시그니처
public<U> Optional<U> flatMap(Function<super T, Optional<U>> mapper);
// 예제
String result = Optional.of("result")
        .flatMap((val) -> Optional.of("good"))
        .get();
System.out.println(result); // print 'good'
cs
 

 

➡️Optional 종단처리

>.ifPresent

최종적으로 연산을 끝낸 후 값이 비어있지 않다면 입력값으로 주어진다. 이 값을 가지고 원하는 작업을 수행하면 된다. 하지만 중간 연산을 하다 비어있는 옵셔널 객체를 받게 되면 .ifPresent() 메서드의 내용을 수행하지 않는다.

1
2
3
4
5
6
7
8
9
10
// 메서드 시그니처
public void ifPresent(Consumer<super T>; consumer);
// 예제1
Optional.of("test").ifPresent((value) ->; {
    // something to do
});
// 예제2 (ifPresent 미수행)
Optional.ofNullable(null).ifPresent((value) ->; {
    // nothing to do
});
cs

 

 

>.isPresent

최종적으로 연산을 끝낸 후 객체가 존재하는지 여부를 판별한다.

1
2
3
4
5
// 메서드 시그니처
public boolean isPresent();
// 예제
Optional.ofNullable("test").isPresent(); // true
Optional.ofNullable("test").filter((val) ->"result".eqauls(val)).isPresent(); // false
cs

 

>.get

: 최종적으로 연산을 끝낸 후 객체가 존재하는지 여부를 판별한다. 없으면 예외를 던진다.

1
2
3
4
5
// 메서드 시그니처
public T get();
// 예제
Optional.of("test").get(); // 'test'
Optional.ofNullable(null).get(); // NoSuchElementException
cs

 

>.orElse

: 최종적으로 연산을 끝낸 후에도 Optional객체가 비어있다면 기본값으로 제공할 객체를 지정한다.

1
2
3
4
5
/ 메서드 시그니처
public T orElse(T other);
// 예제
String result = Optional.ofNullable(null).orElse("default");
System.out.println(result); // print 'default'
cs

 

>.orElseGet

: 최종적으로 연산을 끝낸 후에도 옵셔널 객체가 비어있다면 기본값으로 제공할 공급자 함수를 지정합니다.

1
2
3
4
5
// 메서드 시그니처
public T orElseGet(Supplier<extends T> other);
// 예제
String result = Optional.ofNullable("input").filter("test"::equals).orElseGet(() ->"default");
System.out.println(result); // print 'default'
cs

 

 

>.orElseThrow

최종적으로 연산을 끝낸 후에도 Optional객체가 비어있다면 예외 공급자 함수를 통해 예외를 발생시킨다.

1
2
3
4
// 메서드 시그니처
public <extends Throwable> T orElseThrow(Supplier<extends X> exceptionSupplier) throws X;
// 예제
Optional.ofNullable("input").filter("test"::equals).orElseThrow(NoSuchElementException::new);
cs

 

 

orElse, orElseGet 중 무엇을 사용할까?

orElse 메서드는 옵셔널 객체가 비어있든 비어있지 않든 반드시 실행 한다. orElseGet 메서드는 옵셔널 객체가 비어있으면 실행합니다. 따라서 기본값을 주고자 할때에 기본값을 구하는 과정이 오래 걸린다면 orElseGet을 사용하는게 좋다.

 

 

 

👉다음에는 JAVA9,JAVA10 에 추가된 메서드를 추가해볼 예정이다.

 


Reference

728x90

'Dev > JAVA' 카테고리의 다른 글

[Code] Refactoring , 리펙토링  (0) 2022.02.28
[Design Pattern] 빌더 패턴(Builder Pattern)  (0) 2021.12.02
[JAVA]상속(Inheritance)  (0) 2021.06.16
[JAVA]삼항연산자(Ternary Operator)  (0) 2021.06.15
[JAVA]Primitive type과 Reference type  (0) 2021.04.07