본문 바로가기
JAVA

Optional

by 글발 2023. 9. 17.
728x90
반응형

Optional이란?

Optional은 객체를 담는 그릇이다.

객체가 존재할 수도 있고 아닐수도 있는 경우 즉, null이 될 수도 있다면 Optional에 담는다.

Optional은 null이 될 수도 있는 객체를 감싸는 래퍼 클래스이다.

Java8부터 지원되는 Optional을 활용하면 null 체크하는 부분에서 개발의 효율을 올릴 수 있다.

쉽게 생각해서 원소가 최대 하나 밖에 없는 Collection이나 Stream으로 생각해도 된다

 

Optional 사용 이유

  • NPE(Null Pointer Exception)를 유발할 수 있는 객체를 직접 다루지 않아도 된다.
  • 일일이 null 체크를 직접 하지 않아도 된다.
  • 명시적으로 해당 변수(객체)가 null일 수도 있다는 가능성을 표현할 수 있다.(불필요한 방어로직을 줄임)

Optional 사용 방법

Optional 변수 선언

Optional<Member> optMember;	// Member 타입의 객체를 감싸는 Optional 타입의 변수
Optional<Order> maybeOrder; // Order 타입의 객체를 감싸는 Optional 타입의 변수

변수명은 그냥 클래스명을 사용하기도 하고

'maybe'나 'opt'와 같은 접두어를 붙여서 Optional 타입의 변수라는 것을 나타내기도 한다.

Optional 객체 생성

Optional 클래스는 객체 생성을 위해 세가지 정적 팩토리 메서드를 제공한다.

  • Optional.empty()

null을 담고 있는(비어있는) Optional 객체를 얻어온다.

이 비어있는 객체는 Optional 내부적으로 미리 생성해 놓은 싱글턴 인스턴스이다.

Optional<Member> maybeMember = Optional.empty();
  • Optional.of(value)

null이 아닌 객체를 담고 있는 Optional 객체를 생성한다.

null이 넘어올 경우 NPE를 던지기 때문에 주의해야 한다.

Optional<Member> maybeMember = Optional.of(Member);
  • Optional.ofNullable(value)

null인지 아닌지 확신할 수 없는 객체를 담고 있는 Optional 객체를 생성한다.

Optional.empty()와 Optional.of(value)를 합쳐놓은 메서드라고 생각하면 된다.

null이 넘어올 경우 NPE를 던지지 않고 Optional.empty()와 동일하게 비어있는 Optional 객체를 얻어온다.

해당 객체가 null인지 아닌지 확신할 수 없다면 Optional.ofNullable(value)를 사용해야한다.

Optional<Member> maybeMember = Optional.ofNullable(Member);
Optional<Member> optMembber = Optional.ofNullable(null);

 

Optional이 담고 있는 객체에 접근

Optional 클래스는 담고 있는 객체를 꺼내기 위해 다양한 인스턴스 메서드를 제공한다.

Optional이 담고 있는 객체가 존재할 경우 동일하게 해당 값을 반환하므로

Optional이 비어있는 경우(null을 담고 있는 경우)에 대해서 알아보자.

  • get()

비어있는 Optional 객체에 대해서 NoSuchElementException을 던진다.

  • orElse(T other)

비어있는 Optional 객체에 대해서 넘어온 인자를 반환한다.

이 때, orElse 메서드는 Optional 객체가 비어있든 아니든 메서드를 호출하여 기본 값을 계산한다.

  • orElseGet(Supplier<? extends T> other)

비어있는 Optional 객체에 대해서 넘어온 함수형 인자를 통해 생성된 객체를 반환한다.

이 떄, orElseGet 메서드는 Optional 객체가 비어있을 때만 기본 값을 계산하기 위해 호출된다.

orElse에 비해 게으른(lazy) 계산을 지원하며 기본 값 계산에 비용이 많이 드는 경우 효율적이다.

  • orElseThrow(Supplier<? extends X> exceptionSupplier)

비어있는 Optional 객체에 대해서 넘어온 함수형 인자를 통해 생성된 예외를 던진다.

 

 

추가로 isPresent()와 ifPresent() 까지만 알아보자.

  • isPresent()

Optional 객체가 감싸고 있는 값이 존재하면 true, 비어있다면 false를 반환한다.

  • ifPresent(Consumer<? super T> consumer)

Optional 객체가 감싸고 있는 값이 존재할 경우에만 실행될 로직을 함수형 인자로 넘길 수 있다.

함수형 인자로 람다식이나 메서드 레퍼런스가 넘어올 수 있다.(마치 비동기 메서드 콜백함수 처럼 작동)

아래는 회원 이름이 중복되면 예외를 던지는 예시이다.

private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
                .ifPresent(m -> {
                    throw new IllegalStateException("이미 존재하는 회원입니다.");
                });
    }

 

 

이상으로

간단하게 Optional에 대해서 알아보았다. 잘 활용하면 null 체크를 수월하게 관리할 수 있을거 같다.

 

참고로 Stream 클래스가 가지고 있는 map(), filter()와 같은 메서드를 Optional도 가지고 있다.

사용방법은 같고 Optional은 원소가 최대 하나 밖에 없어서 오히려 쉽다.

'JAVA' 카테고리의 다른 글

문자열 유효성 검증 StringUtils.hasText(String)  (0) 2024.09.07
static import  (1) 2024.01.08