BE/Java

[Java] Optional

baek-dev 2024. 12. 6. 22:01

값을 포함하거나 포함하지 않을수 있는 객체

`null`값을 직접 반환하는 대신 `Optional`객체를 반환하여 값의 유무를 명시적으로 처리하도록 함

 

1. Optional 생성

1.1. Optional.of()

  • `null`이 아닌 값을 가진 객체를 생성
  • `null`값을 전달하면 NullPointerException이 발생
Optional<String> opt = Optional.of("Hello");

 

1.2. Optional.ofNullable()

  • `null`값을 허용하며, 값이 `null`이면 비어있는 객체를 생성
Optional<String> opt = Optional.ofNullable(null);
// opt 는 Optional.empty();

 

1.3. Optional.empty()

  • 값이 비어있는 객체 생성

 

2. 메서드

2.1. isPresent()

  • 값이 존재하면 `true` 존재하지않으면 `false`를 반환
Optional<String> opt = Optional.of("Hello");
System.out.println(opt.isPresent());	// true

 

2.2. ifPresent()

  • 값이 존재하면 주어진 작업을 수행
Optional<String> opt = Optional.of("Hello");
opt.ifPresent(value -> System.out.println(value));	// Hello

 

2.3. get()

  • 값이 존재하면 값을 반환
  • 없으면 `NoSuchElementException`이 발생하므로 주의
Optional<String> opt = Optional.of("Hello");
System.out.println(opt.get());	// Hello

 

2.4. orElse()

  • 값이 있으면 값을 반환, 없으면 기본값을 반환
Optional<String> opt = Optional.empty();
System.out.println(opt.orElse("Default")); // Default

 

2.5. orElseGet()

  • 값이 있으면 값을 반환, 없으면 람다표현식이나 메서드 참조로 기본값을 생성하여 반환
Optional<String> opt = Optional.empty();
System.out.println(opt.orElseGet(() -> "Generated Default")); // Generated Default

 

2.6. orElseThrow()

  • 값이 있으면 반환, 없으면 예외를 발생
Optional<String> opt = Optional.empty();
opt.orElseThrow(() -> new IllegalStateException("값이 없습니다."));

 

2.7. filter()

  • 값이 존재하고 주어진 조건을 만족하면 값을 포함한 `Optional`을 반환하고, 그렇지않으면 빈 `Optional`을 반환
Optional<String> opt = Optional.of("Hello");
Optional<String> filtered = opt.filter(value -> value.startsWith("H"));
System.out.println(filtered.isPresent()); // true

 

2.8. map()

  • 값을 변환하여 새 객체로 반환
  • 값이 없으면 빈 객체 반환
Optional<String> opt = Optional.of("Hello");
Optional<Integer> lengthOpt = opt.map(String::length);
System.out.println(lengthOpt.get()); // 5

 

2.9. flatMap()

  • 객체를 반환하는 매핑함수에 사용됨
  • map과 달리 중첩된 객체를 한단계로 펼침
Optional<String> opt = Optional.of("Hello");
Optional<String> upperCaseOpt = opt.flatMap(value -> Optional.of(value.toUpperCase()));
System.out.println(upperCaseOpt.get()); // HELLO

 

 

3. Optional 예제

3.1.  NullPointerException 방지

public String getName(Person person) {
    return Optional.ofNullable(person)
                   .map(Person::getName)
                   .orElse("Unknown");
}

 

3.2. 데이터베이스 조회 예제

public Optional<User> findUserById(int id) {
    User user = database.queryUser(id); // null 가능
    return Optional.ofNullable(user);
}

Optional<User> userOpt = findUserById(123);
userOpt.ifPresent(user -> System.out.println(user.getName()));

 

3.3. 조건에 따라 값 처리

Optional<String> opt = Optional.of("Java Optional");
opt.filter(value -> value.contains("Java"))
   .ifPresent(System.out::println); // Java Optional

 

 

4. Optional 장점

  • 명시적인 null처리 - 메서드 반환값에서 값이 없음을 명시적으로 알 수 있다
  • NullPointerException 방지 - null을 직접 다루지 않아 NPE 발생 가능성이 줄어든다
  • 가독성 향상 - 값이 없을 경우를 처리하는 코드가 더 명확해진다
  • 함수형 프로그래밍 스타일 - 간결하고 선언적인 코드 작성 가능하다

 

5. 주의사항

  • 필드에 사용 금지
  • 값이 없는 상태로 get() 금지 - `isPresent`로 확인후 사용하거나 `orElse`사용
  • 기본자료형 Optional - `OptionalInt`, `OptionalDouble`등의 클래스 사용이 권장

 

6. Optional의 대안

  • null 자체를 잘 관리한다면 Optional을 사용할 필요는 없다
  • 값이 있을수도 있고, 없을수도 있는 상황에서만 사용

 

 

 

 

출처 : ChatGPT

'BE > Java' 카테고리의 다른 글

[Java] 스트림  (1) 2024.12.09
[Java] Map  (0) 2024.12.07
[Java] List  (1) 2024.12.05
[Java] 컬렉션  (0) 2024.12.04
[Java] 래퍼 클래스  (0) 2024.12.03