Programming/Java

[Java] Optional<T> 이란? (개념/ 종류 별/ 사용 방법/ 예제)

JeongKyun 2022. 5. 21.

서론


프로그래밍을 하다보면 가장 조심해야할 에러 중 하나가 NPE(NullPointException)이다.

 

이 NPE는 보통 컴파일할 때 잡지 못하고 실행 중 갑자기 발생하는 에러이기에 잘못 걸리면 엄청 골치아파지는 에러 중 하나이기 때문이다.

 

그래서 우리는 보통 NPE를 방지하기 위해 null 검사 로직을 넣게 되는데 이 null인지를 검사하는 로직이 추가될 수록 코드가 복잡해지고 지저분해질 수 있다.

 

이번에 그래서 Java에서 Optional이라는 NPE를 방지할 수 있는 함수형 클래스를 지원해주게 되었는데, 어떻게 사용하고 사용하면 어떤 효과가 있는지 알아보자.

 


 

NPE(NullPointException) 이란?


    public static void main(String[] args) {

        Map<Integer,String> map = null;
        map.clear();
    }

 

실행 결과

 

위와 같이 map의 값이 null인 상태에서 어떠한 동작을 하게되면 결과 이미지와 같읕 에러가 발생하는데 문구를 보면 NPE인 것을 확인할 수 있다. 이와 같이 해당 값이 null인 상태에서 어떠한 값을 넣거나 동작을 하게되면 발생하는 에러이다.

 


 

Optional<T> 알아보기 (총 정리)


Optional<T> 생성 함수

public static <T> Optional<T> of(T value)

public static <T> Optional<T> empty()

public static <T> Optional<T> ofNullable(T value)

 

Optional을 생성하는 방법은 위와같이 3가지가 있다. 하나씩 알아보자.

 

of

Null이 아닌 오브젝트를 이용하여 Optional을 만들 때 사용한다.

 

Empty

빈 Optional을 만들 때 사용한다.

 

ofNullable

Null 인지 아닌지 알지 못하는 오브젝트로 Optional을 만들 때 사용한다.

 

 

 

Optional<T> 생성 함수 예제

        String someEmail = "dkswjdrbs12@naver.com";
        String nullEmail = null;

        Optional<String> maybeEmail = Optional.of(someEmail);
        Optional<String> maybeEmail2 = Optional.empty();
        Optional<String> maybeEmail3 = Optional.ofNullable(someEmail);
        Optional<String> maybeEmail4 = Optional.ofNullable(nullEmail);
        
        System.out.println(maybeEmail);
        System.out.println(maybeEmail2);
        System.out.println(maybeEmail3);
        System.out.println(maybeEmail4);

실행 결과

 

위와 같이 각 속성에 맞게 작성하여 Optional을 생성하는 것을 확인할 수 있다.


 

Optional<T> 사용 함수

public boolean isPresent()

public T get()

public T ofElse(T other)

public T orElseGet(Supplier<? extends T> supplier)

public <X extends Throwable> T orElseThrow(
        Supplier<? extends X> exceptionSupplier) throws X

 

Optional 안에 있는 값을 확인하고 꺼내는 방법은 다음과 같다. 하나씩 알아보자.

 

isPresent

안의 오브젝트가 null인지 아닌지 체크하고 null이 아닐 시 true를 반환한다.

 

get

Optional 안의 값을 추출하고 null이라면 에러를 반환한다.

 

orElse

Optional이 null이 아니라면 Optioanl 안의 값을 null이라면 other로 공급된 값을 반환한다.

 

orElseGet

Optional이 null이 아니라면 Optioanl 안의 값을 반환, null이라면 Supplier로 공급되는 값을 반환한다.

 

orElseThrow

Optional이 null이 아니라면 Optional 안의 값을 반환, null이라면 exceptionSupplier로 공급되는 exception을 반환한다.

 

 

 

Optional<T> 사용 함수 예제

        String someEmail = "dkswjdrbs12@naver.com";
        String nullEmail = null;

        Optional<String> maybeEmail = Optional.of(someEmail);
        Optional<String> maybeEmail2 = Optional.empty();
        Optional<String> maybeEmail3 = Optional.ofNullable(someEmail);
        Optional<String> maybeEmail4 = Optional.ofNullable(nullEmail);
        
        String email = maybeEmail.get();
        System.out.println(email);

        if(maybeEmail.isPresent()){
            System.out.println(maybeEmail.get());
        }

        String defaultEmail= "default@email.com";
        String email3 = maybeEmail2.orElse(defaultEmail);
        String email4 = maybeEmail2.orElseGet(() -> defaultEmail);
        String email5 = maybeEmail.orElseThrow(() -> new RuntimeException("email not present"));
        
        System.out.println(email3);
        System.out.println(email4);
        System.out.println(email5);

실행 결과

 

위의 예제를 실행하면 다음과 같은 결과가 나온다.

만약 orElseThorw()의 함수에서 maybeEmail을 maybeEmail2로 바꾸면 어떻게 될까? 아래에서 확인해보자.

 

 

orElseThorw()의 값이 null이면 ?

orElseThorw empty값 실행 결괴

 

위와 같이 지정한 RuntimeException가 발생하는 것을 확인할 수 있다.

 


자주 쓰이는 Optional<T> 응용 함수

public void ifPresent(Consumer<? super T> action)

public <U> Optional<U> map(Function<? super T, ? extends U> mapper)

 

ifPresent

Optional이 null이 아니라면 action을 실행한다.

 

map

Optional이 null이 아니면 map에서 지정한 값을 반환한다.

 

 

 

자주 쓰이는 Optional<T> 응용 함수 예제

        /* ifPresent 예제 */
        Optional<String> str = Optional.ofNullable("NPE가 싫어요");        
        
        //null이 아니고 값이 있다면 값 표출하라.
        str.ifPresent(System.out::println);
        
        
                
        /* map + ifPresent 예제 */
        //null이 아니면 strValue에 "22"를 넣는다. null이면 아무것도 안넣는다.
        Optional<String> str2 = Optional.ofNullable("NPE가 싫어요")
        .map(user -> "22");
        
        str2.ifPresent(System.out::println);

실행 결과

 


 

마치며..


이렇게 NPE에 대한 부분을 크게 덜어줄 수 잇는 Optional이라는 클래스에 대해 알아보았고 이것을 잘만 응용하면 간결하고 NPE로부터 안전한 소스를 만들 수 있다. 

 

실제 현업에서도 NPE 방지를 위해 Optional 클래스를 많이들 사용하는 것으로 알고있다.

 

이번 기회에 스터디해서 본인의 프로젝트에 적용해보자 !

반응형

댓글

💲 많이 본 글