Backend/Java

[Java] Optional 한눈에 정리하기

누구세연 2024. 11. 19. 08:31

Optional은 Java 8에 도입된 클래스로 null 처리를 안전하게 하고 코드의 가독성을 높이는 데 도움을 줍니다.

이 글에서는 Optional에 대해 간단하게 정리해 보겠습니다. 👩🏻‍💻

 

Optional 기본 개념

Optional은 값이 존재할 수도 있고 없을 수도 있는 상황을 명시적으로 표현합니다.

  • NullPointerException 방지
    값을 감싸는 컨테이너 역할을 하며, null일 가능성을 안전하게 처리
  • Optional 사용 이유
    • 명시적으로 값이 없음을 표현(`Optional.empty()`)
    • null 대신 의미 있는 API 설계
    • null 체크를 명시적으로 처리

Optional 생성 방법

1) 빈 Optional 생성

Optional<String> emptyOptional = Optional.empty();

2) null이 아닌 값으로 생성

Optional<String> optional = Optional.of("Hello, World!");

3) null 허용(Optional 값이 null일 수 있음)

Optional<String> nullableOptional = Optional.ofNullable(null);
  • null일 경우 `Optional.empty()`반환

주요 메서드

1) isPresent()/ isEmpty()

값이 있는지 없는지 확인할 수 있습니다.

Optional<String> optional = Optional.of("Hello");
System.out.println(optional.isPresent()); // true
System.out.println(optional.isEmpty());   // false

2) get()

Optional에 값이 있는 경우 값을 반환하고 값이 없으면 `NoSuchElementException`발생(사용 시 주의)

Optional<String> optional = Optional.of("Hello");
System.out.println(optional.get()); // "Hello"

3) orElse()

값이 있으면 반환, 없으면 기본값 반환합니다.

String value = Optional.ofNullable(null).orElse("Default Value");
System.out.println(value); // "Default Value"

4) orElseGet()

값이 없을 때, 람다 표현식(지연 계산)을 통해 기본값을 생성합니다.

String value = Optional.ofNullable(null)
                        .orElseGet(() -> "Generated Default Value");
System.out.println(value); // "Generated Default Value"

5) orElseThrow()

값이 없을 때 예외를 던집니다.

String value = Optional.ofNullable(null)
                        .orElseThrow(() -> new IllegalArgumentException("Value is missing!"));

6) ifPresent()

값이 있는 경우 실행할 동작을 지정합니다.

Optional<String> optional = Optional.of("Hello");
optional.ifPresent(System.out::println); // "Hello"

7) map()

Optional의 값을 변환합니다.

Optional<String> optional = Optional.of("Hello");
Optional<Integer> length = optional.map(String::length);
System.out.println(length.get()); // 5

8) flatMap()

중첩된 Optional을 평면화합니다.

Optional<Optional<String>> nestedOptional = Optional.of(Optional.of("Hello"));
Optional<String> flat = nestedOptional.flatMap(o -> o);
System.out.println(flat.get()); // "Hello"

9) filter()

조건에 맞는 값만 남깁니다.

Optional<String> optional = Optional.of("Hello");
Optional<String> filtered = optional.filter(s -> s.startsWith("H"));
System.out.println(filtered.isPresent()); // true

 


Optional 사용 예시

1) 메서드 반환값 처리

Optional을 반환해 null 반환을 방지합니다.

public Optional<String> findUserById(String id) {
    return Optional.ofNullable(userRepository.getUser(id));
}

2)Null 체크 코드 간소화

기존 코드

String value = (obj != null && obj.getProperty() != null) ? obj.getProperty() : "Default";

Optional 활용

String value = Optional.ofNullable(obj)
                       .map(Object::getProperty)
                       .orElse("Default");

3) 값 처리 시 안전한 호출

Optional<String> username = Optional.ofNullable(user.getUsername());
username.ifPresent(name -> System.out.println("Hello, " + name));

Optional 사용 시 주의 사항

  1. 필드에 Optional 사용 금지: 직렬화, 메모리 문제 가능성
    - 대신 null로 초기화하거나 기본값 설정
  2. get() 최소화: 값이 없을 경우 예외 발생. 반드시 존재를 확신할 때만 사용.
  3. Optional로 모든 null 대체는 과잉 설계: 단순히 null 체크를 복잡하게 만들 수 있음.

 

💡 Optional 은 null 처리와 코드의 안정성을 높이는 데 유용하지만, 올바르게 사용해야 오히려 복잡성을 줄이고 가독성을 높일 수 있습니다.
주요 메서드를 적절히 활용해 명시적이고 안전한 코드를 작성하면 좋을 것 같습니다! 😊