IT

[Java] Optional

data-cloud 2025. 1. 22. 22:10
반응형

 

 

☕️ Optional이란?

Optional은 NULL이 올 수 있는 값을 감싸는 Wrapper 클래스로, Java 8에서 추가되었으며 NULL을 보다 편리하게 핸들링하여 NPE을 발생하지 않도록 도와준다.

 

 

☕️ Optional 생성

Optional은 아래와 같은 방법으로 생성할 수 있다.

  • Optional.of(T value)
    - value를 Optional로 감싼 객체를 생성한다. 이때 주의할 점은 만약 value가 null이라면 NPE가 발생한다.

  • Optional.ofNullable(T value)
    - value를 Optional로 감싼 객체를 생성한다. Optional.of()와의 차이점은 value가 null이라도 NPE가 발생하지 않는다.

  • Optional.empty()
    - 빈 객체를 생성한다.
import java.util.Optional;

public class OptionalEx {

    public static void main(String[] args) {
        /** 1. Optional.of() */
        Optional<String> opt1 = Optional.of("aaa");
        System.out.println(opt1); // Optional[aaa]
        System.out.println(opt1.get()); // aaa

        // Optional<String> opt2 = Optional.of(null); // NPE 발생


        /** 2. Optional.ofNullable() */
        Optional<String> opt3 = Optional.ofNullable(null); // NPE이 발생하지 않는다.
        System.out.println(opt3); // Optional.empty
        // System.out.println(opt3.get()); // NoSuchElementException 발생



        /** 3. Optional.empty() */
        // Optional<String> nullOpt1 = null;
        Optional<String> nullOpt2 = Optional.empty(); // 초기화 값을 지정하지 않고 초기화할 경우, null 대신 Optional.empty() 권장
    }

}

 

 

반응형

 

☕️ Optional로 NULL 판단

Optional은 아래의 메서드를 사용하여 NULL여부를 판단할 수 있다.

  • Optional.isPresent()
    - 값이 있다면 TRUE를 반환하고, 값이 없다면 FALSE를 반환한다.

  • Optional.isEmpty()
    - isPresent()와 반대로 값이 없다면 TRUE를 반환하고, 값이 있다면 FALSE를 반환한다.
import java.util.Optional;

public class OptionalEx {

    public static void main(String[] args) {

        Optional<String> optNull1 = Optional.ofNullable("ABC");
        System.out.println(optNull1.isPresent()); // true
        System.out.println(optNull1.isEmpty()); // false

        Optional<String> optNull2 = Optional.ofNullable(null);
        System.out.println(optNull2.isPresent()); // false
        System.out.println(optNull2.isEmpty()); // true
    }

}

 

 

 

☕️ Optional로 값 가져오기

Optional은 아래의 메서드를 사용하여 값을 가져올 수 있다.

  • Optional.get()
    - Optional 안의 값을 가져온다. 단, 값이 NULL이면 NoSuchElementException이 발생한다.

  • Optional.orElse(T other)
    - Optional 안의 값을 가져온다. 만약 값이 NULL이라면 other값으로 대체한다.

  • Optional.orElseGet(Supplier<? extends T> supplier)
    - Optional 안의 값을 가져온다. 만약 값이 NULL이라면 함수형 인터페이스를 수행한 결과로 대체한다.
import java.util.Optional;

public class OptionalEx {

    public static void main(String[] args) {
        String nullStr = null;
        String notNullStr = "ABC";

        // System.out.println(Optional.ofNullable(nullStr).get()); // NoSuchElementException 발생
        System.out.println(Optional.ofNullable(notNullStr).get()); // ABC

        System.out.println(Optional.ofNullable(nullStr).orElse("XYZ")); // XYZ
        System.out.println(Optional.ofNullable(notNullStr).orElse("XYZ")); // ABC

        System.out.println(Optional.ofNullable(nullStr).orElseGet(() -> "XYZ")); // XYZ
        System.out.println(Optional.ofNullable(notNullStr).orElseGet(() -> "XYZ")); // ABC
    }

}

 

 

 

☕️ Optional.orElse()과 Optional.orElseGet()의 차이

orElse()과 orElseGet() 메서드 모두 값이 NULL일 때 방어코드 용도로 사용할 수 있는 메서드이다.
하지만 두 개의 메서드에는 큰 차이점이 있다. orElse()는 null값 여부와 상관없이 항상 호출되고, orElseGet()는 null일 때만 호출된다.
따라서 두 개의 메서드를 제대로 알고 사용하지 않는다면 수행결과에 있어서 다른 결과를 초래할 수 있게 될 수 있으니 주의하자.

import java.util.Optional;

public class OptionalEx {

    public static void main(String[] args) {
        String nullStr = "ABC";
        String notNullStr = null;

        System.out.println(Optional.ofNullable(nullStr).orElse(getDefaultValue()));
        /* - 실행결과
         *   # getDefaultValue() 실행
         *   default
         */
        
        System.out.println(Optional.ofNullable(notNullStr).orElse(getDefaultValue()));
        /* - 실행결과 (NULL이 아닌데도 getDefaultValue()가 수행된다.)
         *   # getDefaultValue() 실행
         *   ABC
         */

        System.out.println(Optional.ofNullable(nullStr).orElseGet(OptionalEx::getDefaultValue));
        /* - 실행결과
         *   # getDefaultValue() 실행
         *   default
         */
        
        System.out.println(Optional.ofNullable(notNullStr).orElseGet(OptionalEx::getDefaultValue));
        /* - 실행결과 (NULL이 아니어서 getDefaultValue()가 수행되지 않았다.)
         *   ABC
         */
    }

    static String getDefaultValue() {
        System.out.println("# getDefaultValue() 실행");
        return "default";
    }

}

 

 

 

☕️ Optional로 예외 발생시키기

Optional은 아래의 메서드를 사용하여 예외를 발생시킬 수 있다.

  • Optional.orElseThrow(Supplier<? extends X> exceptionSupplier)
    - Optional 안의 값이 NULL이라면 예외를 발생시킨다.
import java.util.Optional;

public class OptionalEx {

    public static void main(String[] args) {
        String userName = "CHOI";
        String userNullName = null;
        System.out.println(Optional.ofNullable(userName).orElseThrow(IllegalArgumentException::new)); // CHOI
        System.out.println(Optional.ofNullable(userNullName).orElseThrow(IllegalArgumentException::new)); // IllegalArgumentException 발생
    }

}

 

orElseThrow() 메서드를 적절하게 사용한다면 코드의 가독성을 높일 수 있다는 장점이 있다.
JPA에서 상품을 조회하는 로직을 통해 그 예시를 알아보자.

public class ItemService {
	Item findItemById(Long itemId) {
    	Optional<Item> item = itemRepository.findById(itemId);
        if(item.isEmpty()) {
        	throw new NoSuchElementException();
        }
        
    	return item.get();
    }
   
    // orElseThrow를 사용하여 가독성 높이기
    Item findItemById_orElseThrow(Long itemId) {
    	return itemRepository.findById(itemId)
            .orElseThrow(() -> new NoSuchElementException());
    }
}

 

 

 

 

 

References.

1. 망나니개발자 - [Java] Optional이란? Optional 개념 및 사용법 - (1/2)
2. highright96 - java.util.Optional이란? 

 

반응형