티스토리 뷰
1. Optional
:: 값이 존재할 수도 있고, 존재하지 않을 수도 있는 상황을 명시적으로 표현
:: null이 올 수 있는 값을 감싸는 Wrapper 클래스
:: 객체 참조 시, NPE에 대한 방지 목적
- NPE(Null Pointer Exception)
- Null 값인 객체에 참조할 때 발생
- 해결 방법
- null 체크 → 버거로움
- optional
- 디버깅 도구 사용
- null을 허용하지 않는 설계 → 초기값 부여
장점 | - optional을 사용하는 경우 코드가 Null-safe해짐 - 가독성 향상 - 애플리케이션이 안정적 |
side-Effect(잘못 쓸 경우) | - NullPointerException 대신 NoSuchElementException 유발 - 직렬화의 경우, 이전에 없던 문제 발생 - 오버헤드의 위험성 |
1.1 Optional 기본 구조
public final class Optional<T> {
private final T value;
...
}
- 생성 방법
// 1. 값이 null일 경우
Optional<T> optional = Optional.empty(); // 값이 없음
// 2. 값이 null이 아닐 경우
Optional<T> optional = Optional.of(객체); // 값이 무족건 있어야 함
// 3. 값이 null이될 수도 있을 경우
Optional<T> optional = Optional.ofNullable(객체); // 값 허용
// ofNullable의 경우 null 값에 대한 처리를 위해
// .orElse(대체 객체)
// .orElseGet(대체 객체)
// .orElseThrow(예외::new) null 일 경우 예외를 발생
- 추가적인 예시
Optional<String> optional = Optional.of("Hello");
// map: 값을 변환
Optional<String> upperCase = optional.map(String::toUpperCase);
System.out.println(upperCase.orElse("Default")); // 출력: HELLO
// flatMap: 중첩된 Optional안의 값에 접근
Optional<String> flatMapped = optional.flatMap(s -> Optional.of(s + " World"));
System.out.println(flatMapped.orElse("Default")); // 출력: Hello World
// filter: 조건에 맞는 값만 유지
Optional<String> filtered = optional.filter(s -> s.length() > 10);
System.out.println(filtered.orElse("Too Short")); // 출력: Too Short
1.2 올바른 사용 방법
1. optional 변수에 null 할당 자제
2. 값이 없을 때는 Optional.orElse(Get)()로 기본 값 반환
3. 단순히 값을 얻으려는 목적으로만 Optional 사용 X
Optional<String> opt = findValue();
opt.ifPresent(value -> System.out.println(value)); // 값이 있을 때만 처리
4. 생성자, 수정자, 메소드 파라미터로 Optional 자제
5. Collection의 경우 Optional이 아닌 비어있는 Collection을 사용 권고
List<String> result = getNames().orElse(Collections.emptyList());
6. 반환 타입으로만 사용 권고
public Optional<String> findNameById(int id) {
return Optional.ofNullable(nameMap.get(id)); // 반환 타입으로만 사용
}
1.3 관련 메서드
1.4 orElse()와 orElseGet() 비교
:: 값이 null일 경우 해당 값을 반환하는 메소드
- orElse
:: 파라미터로 “값” 을 받음
:: 값이 미리 존재하는 경우 사용
:: 메소드가 other로 들어갈 경우 → 무조건 실행됨
public T orElse(T other) {
return value != null ? value : other;
} // other을 그대로 반환
- orElseGet
:: 파라미터로 “함수형 인터페이스”를 받음
:: 값이 미리 존재하는 않는 거의 대부분의 경우 사용
:: value is null 일 경우, other의 get이 실행(지연실행으로 인해 null일때 바로 호출 X)
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
} // Supplier의 인터페이스를 통해 결과를 반환
메소드 | 기본값 계산 시점 | 성능 차이(비용) |
orElse | 즉시 계산 | 항상 기본값을 계산하므로 기본값이 비싸면 성능 저하 |
orElseGet | 지연 계산 | Optional이 비어 있을 때만 기본값 계산, 성능 상 이점 |
// orElse 사용:
Optional<String> opt = Optional.empty();
String result = opt.orElse(expensiveOperation());
// expensiveOperation이 항상 호출됨
// orElseGet 사용:
Optional<String> opt = Optional.empty();
String result = opt.orElseGet(() -> expensiveOperation());
// 필요한 경우에만 expensiveOperation 호출
1.5 중간에 막혔던 부분
public static <T> Optional<T> getAsOptional(List<T> list, int index) {
try {
return Optional.of(list.get(index));
} catch (ArrayIndexOutOfBoundsException e) {
return Optional.empty();
}
}
타입에 대해 독립적인 메서드를 위해 위와 같이 표현
처음의 <T>는 뒤의 List<T>를 정해주기 위해 등장
아래와 같이 사용됨
Optional<String> maybeCity = getAsOptional(cities, 3); // Optional
int length = maybeCity.map(String::length).orElse(0); // null-safe
System.out.println("length: " + length);
참조
ASAC 수업자료
자바8 Optional 3부: Optional을 Optional답게
Java Development Kit Version 16 API Specification
[JAVA Optional] Optional에 대해 알아보자
'정리용 > java' 카테고리의 다른 글
[JAVA] 기초 8. 함수형 인터페이스 - 끝.. (0) | 2025.02.04 |
---|---|
[JAVA] 기초 8. 함수형 인터페이스 - Monad (0) | 2025.02.04 |
[JAVA] 기초 7. 키워드 Enum (1) | 2025.02.04 |
[JAVA] 기초 4-1 다형성과 상속 (0) | 2025.02.04 |
[JAVA] 기초 6. Generic (0) | 2025.01.23 |
- Total
- Today
- Yesterday
- acac
- useState
- useMemo
- memo
- useCallback
- asac7
- useRef
- useContext
- acas#acas7기
- react
- asac#asac7기
- ssh
- useEffect
- asac7#asac
- useReducer
- ASAC
- asac7기
- useLayoutEffect
- git
- Nginx
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |