Files
java-examples/docs/Optional.md

5.7 KiB

자바 Optional 주요 메서드 정리

메서드 설명
of(T value) null이 아닌 값을 감싸는 Optional 생성
ofNullable(T value) null일 수도 있는 값을 감싸는 Optional 생성
empty() 비어 있는 Optional 생성
isPresent() 값이 존재하면 true, 없으면 false 반환
isEmpty() 값이 없으면 true, 있으면 false 반환
get() 값이 존재하면 반환, 없으면 NoSuchElementException 발생
orElse(T other) 값이 존재하면 반환, 없으면 기본값 반환
orElseGet(Supplier) 값이 존재하면 반환, 없으면 함수 실행 결과 반환
orElseThrow() 값이 존재하면 반환, 없으면 예외 발생
or(Supplier) 값이 존재하면 현재 Optional 반환, 없으면 다른 Optional 반환
ifPresent(Consumer) 값이 존재하면 실행할 코드 지정
ifPresentOrElse(Consumer, Runnable) 값이 존재하면 실행할 코드, 없으면 실행할 코드 지정
map(Function) 값을 변환하여 새로운 Optional 반환
flatMap(Function) 중첩된 Optional을 평탄화하여 반환
filter(Predicate) 조건을 만족하면 Optional 유지, 아니면 비움

자바 Optional 쉽게 설명하기

Optional이란?

자바에서는 null이 자주 등장한다. 하지만 null을 잘못 다루면 NullPointerException(NPE)이 발생한다.
이 문제를 해결하기 위해 나온 것이 **Optional(옵셔널)**이다.

"옵셔널은 값이 있을 수도 있고 없을 수도 있는 박스다."

즉, 값을 안전하게 감싸고 다룰 수 있도록 도와주는 도구다.
값이 있으면 꺼내서 사용하고, 없으면 null 대신 기본값을 사용하거나 예외를 발생시킬 수 있다.


Optional 사용 예제

1. Optional 생성하기

Optional<String> name = Optional.of("Alice");  // 값이 있는 Optional
Optional<String> emptyName = Optional.empty(); // 비어 있는 Optional
Optional<String> nullableName = Optional.ofNullable(null); // null 가능
  • Optional.of(value): null이 아닌 값을 감쌈 (null이면 예외 발생)
  • Optional.empty(): 비어 있는 Optional 생성
  • Optional.ofNullable(value): null일 수도 있는 값을 감쌈

2. 값이 있는지 확인하기

Optional<String> name = Optional.of("Alice");

System.out.println(name.isPresent()); // true
System.out.println(name.isEmpty());   // false
  • isPresent(): 값이 있으면 true
  • isEmpty(): 값이 없으면 true

3. 값 가져오기

Optional<String> name = Optional.of("Alice");

System.out.println(name.get()); // "Alice"

하지만 값이 없을 때 get()을 호출하면 예외가 발생하므로 주의해야 한다.

Optional<String> emptyName = Optional.empty();
System.out.println(emptyName.get()); // NoSuchElementException 발생!

그래서 orElse() 또는 orElseGet()을 사용하는 것이 안전하다.

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

String result1 = emptyName.orElse("Unknown"); // 기본값 제공
String result2 = emptyName.orElseGet(() -> "Generated Name"); // 함수로 기본값 제공

System.out.println(result1); // "Unknown"
System.out.println(result2); // "Generated Name"

4. 값이 없을 때 예외 던지기

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

String name = emptyName.orElseThrow(() -> new IllegalArgumentException("이름이 없습니다!"));

값이 없으면 IllegalArgumentException을 던진다.


5. 값이 있을 때만 실행하기 (ifPresent)

Optional<String> name = Optional.of("Alice");

name.ifPresent(n -> System.out.println("이름: " + n)); // 이름이 있으면 출력

값이 없으면 아무 일도 일어나지 않는다.


6. 값이 있으면 실행, 없으면 다른 작업 수행 (ifPresentOrElse)

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

name.ifPresentOrElse(
    n -> System.out.println("이름: " + n),  // 값이 있을 때 실행
    () -> System.out.println("이름이 없습니다!") // 값이 없을 때 실행
);

7. 값 변환하기 (map)

Optional<String> name = Optional.of("Alice");

Optional<Integer> length = name.map(String::length);

System.out.println(length.get()); // 5
  • map(Function): 값이 있으면 변환하고, 없으면 Optional.empty() 유지

8. 중첩된 Optional을 평탄화 (flatMap)

Optional<Optional<String>> nested = Optional.of(Optional.of("Alice"));

Optional<String> flat = nested.flatMap(n -> n);

System.out.println(flat.get()); // "Alice"
  • flatMap(Function): 중첩된 Optional을 단일 Optional로 변환

9. 조건에 맞는 값만 유지하기 (filter)

Optional<String> name = Optional.of("Alice");

Optional<String> filtered = name.filter(n -> n.startsWith("A"));

System.out.println(filtered.get()); // "Alice"
  • filter(Predicate): 조건을 만족하면 Optional 유지, 아니면 Optional.empty() 반환

Optional을 사용하면 좋은 이유

  1. null 체크가 필요 없음if (value != null) 같은 코드 제거 가능
  2. 코드가 더 읽기 쉬움Optional 메서드를 통해 명확한 의도를 전달
  3. 안전한 값 처리 가능orElse(), ifPresent() 등을 활용하여 null을 안전하게 대체

즉, **"옵셔널은 값이 있을 수도 있고 없을 수도 있는 안전한 박스"**다.
무작정 null을 다루는 것보다 Optional을 활용하면 예외 없이 더 깔끔하고 안전한 코드를 작성할 수 있다.