티스토리 뷰
목차
1. Optional
2. Optional API
1. Optional
1) 자바 프로그래밍에서 NullPointerException을 종종 보게 되는 이유
null을 리턴하니까! && null 체크를 깜빡했으니까!
2) 메소드에서 작업 중 특별한 상황에서 값을 제대로 리턴할 수 없는 경우 선택할 수 있는 방법
- 예외를 던진다. (비싸다, 스택트레이스를 찍어두니까.)
- null을 리턴한다. (비용 문제가 없지만 그 코드를 사용하는 클리어인트 코드가 주의해야 한다.)
- (자바 8부터) Optional을 리턴한다.
(클라이언트에 코드에게 명시적으로 빈 값일 수도 있다는 걸 알려주고, 빈 값인 경우에 대한 처리를 강제한다.)
3) Optional
오직 값 한 개가 들어있을 수도 없을 수도 있는 컨네이너.
4) 주의할 것
- 리턴값으로만 쓰기를 권장한다. (메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드타입으로 쓰지 말자.)
파라미터로 넘어오는 Optional이 null일 수 있기 때문에 null 체크를 하지 않으면 NullPointerException
// setter
public void setProgress(Optional<Progress> progress) {
progress.ifPresent(p -> this.progress = progress.get());
}
// main
OnlineClass spring_boot = new OnlineClass(1, "spring boot", true);
spring_boot.setProgress(null); // NullPointerException
- Optional을 리턴하는 메소드에서 null을 리턴하지 말자. -> 결국 메소드를 호출하는 코드에서 null 체크를 해야함...(Optional.empty() 사용)
- 프리미티브 타입용 Optional은 따로 있다. OptionalInt, OptionalLong,...
- Collection, Map, Stream, Array, Optional은 Opiontal로 감싸지 말 것.
2. Optional API
1) Optional 만들기
Optional.of()
Optional.ofNullable() : 값이 null 일 수도 있는 경우 사용, null인 경우 Optional.empty()
Optional.empty()
public Optional<Progress> getProgress() {
return Optional.ofNullable(progress);
}
2) Optional에 값이 있는지 없는지 확인하기
isPresent()
isEmpty() (Java 11부터 제공)
boolean present = classOptional.isPresent();
boolean empty = classOptional.isEmpty();
3) Optional에 있는 값 가져오기
get() : 비어있는 경우 NoSuchElementException 발생
OnlineClass onlineClass = classOptional.get();
4) Optional에 값이 있는 경우 처리
ifPresent(Consumer) : Optional에 값이 있는 경우에 그 값을 가지고 ~~를 하라.
classOptional.ifPresent(oc -> System.out.println(oc.getTitle()));
5) Optional에 값이 있으면 가져오고 없는 경우 처리
(1) orElse(T) : Optional에 값이 있으면 가져오고 없는 경우에 ~~를 리턴하라.
orElse 의 파라미터가 람다식이나 메소드 참조가 아니기 때문에 값이 없는 경우에도 createNewClass()가 실행이 된다.
OnlineClass onlineClass1 = classOptional.orElse(createNewClass());
(2) orElseGet(Supplier) : Optional에 값이 있으면 가져오고 없는 경우에 ~~를 하라.
orElseGet 의 파라미터로 Supplier 타입을 넘겨준다.
값이 없느 경우에만 createNewClass() 가 실행된다.
OnlineClass onlineClass2 = classOptional.orElseGet(() -> createNewClass());
(3) orElseThrow() : Optional에 값이 있으면 가졍고 없는 경우 에러를 던져라.
OnlineClass onlineClass3 = classOptional.orElseThrow(() -> new IllegalStateException());
6) Optional에 들어있는 값 걸러내기
Optional filter(Predicate)
Optional<OnlineClass> filterOptional = classOptional.filter(oc -> !oc.isClosed());
7) Optional에 들어있는 값 변환하기
Optional map(Function)
Optional<Integer> integer = classOptional.map(OnlineClass::getId);
Optional flatMap(Function): Optional 안에 들어있는 인스턴스가 Optional인 경우에 사용하면 편리하다.
Optional<Optional<Progress>> mapProgress = classOptional.map(OnlineClass::getProgress);
Optional<Progress> progress = mapProgress.orElse(Optional.empty());
Optional<Progress> flatMapProgress = classOptional.flatMap(OnlineClass::getProgress);
전체 소스코드
public static void main(String[] args) {
List<OnlineClass> springClasses = new ArrayList<>();
springClasses.add(new OnlineClass(1, "spring boot", true));
springClasses.add(new OnlineClass(2, "spring data jpa", true));
springClasses.add(new OnlineClass(3, "spring mvc", false));
springClasses.add(new OnlineClass(4, "spring core", false));
springClasses.add(new OnlineClass(5, "rest api development", false));
// Stream 중계형 오퍼레이션에서 Optional 사용
Optional<OnlineClass> classOptional = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("spring"))
.findFirst();
// 값이 있는지 없는지 확인
boolean present = classOptional.isPresent();
System.out.println(present);
boolean empty = classOptional.isEmpty();
System.out.println(empty);
// 꺼내기
// 비어있는 경우 NoSuchElementException 발생
OnlineClass onlineClass = classOptional.get();
System.out.println(onlineClass.getTitle());
// 값이 있는 경우 처리
classOptional.ifPresent(oc -> System.out.println(oc.getTitle()));
// 값이 있는 경우 꺼내고 없는 경우 처리 1
// orElse 의 파라미터가 람다식이나 메소드 참조가 아니기 때문에
// 값이 없는 경우에도 createNewClass()가 실행이 된다.
OnlineClass onlineClass1 = classOptional.orElse(createNewClass());
System.out.println(onlineClass1.getTitle());
// 값이 있는 경우 꺼내고 없는 경우 처리 2
// orElseGet 의 파라미터로 Supplier 타입을 넘겨준다.
// 값이 없느 경우에만 createNewClass() 가 실행된다.
OnlineClass onlineClass2 = classOptional.orElseGet(() -> createNewClass());
// 값이 있는 경우 꺼내고 없는 경우 처리 3
// 값이 없는 경우 exception 이 발생되도록
OnlineClass onlineClass3 = classOptional.orElseThrow(() -> new IllegalStateException());
// 걸러내기
// 값이 없는 경우 Optional.empty 리턴
Optional<OnlineClass> filterOptional = classOptional.filter(oc -> !oc.isClosed());
System.out.println(filterOptional);
// 변환하기
// map
Optional<Integer> integer = classOptional.map(OnlineClass::getId);
// 변환하기 2
// Ontinal<Optinal>
Optional<Optional<Progress>> mapProgress = classOptional.map(OnlineClass::getProgress);
Optional<Progress> progress = mapProgress.orElse(Optional.empty());
Optional<Progress> flatMapProgress = classOptional.flatMap(OnlineClass::getProgress);
}
private static OnlineClass createNewClass() {
return new OnlineClass(10, "New class", false);
}
출처
https://www.inflearn.com/course/the-java-java8 더 자바, Java 8(백기선)
'Java > Java 8' 카테고리의 다른 글
[java 8] 3-2. Stream (리덕션, 병렬 스트림) (0) | 2021.12.29 |
---|---|
[java 8] 3-1. Stream (생성, 중간 연산, 최종 연산) (0) | 2021.12.29 |
[java 8] 3. Stream (0) | 2021.12.17 |
[java 8] 1-1. 함수형 인터페이스와 람다 (메소드 참조) (0) | 2021.12.17 |
[java 8] 2. 인터페이스의 변화 (0) | 2021.12.02 |
- Total
- Today
- Yesterday
- 트랜잭셔널 아웃박스 패턴
- 스프링 카프카 컨슈머
- java8
- clean code
- MySQL
- Spring Data JPA
- Ubiquitous Language
- 학습 테스트
- JPA
- 폴링 발행기 패턴
- Stream
- mockito
- kafka
- H2
- 스프링 예외 추상화
- ATDD
- TDD
- 육각형 아키텍처
- 도메인 모델링
- 이벤트 스토밍
- 마이크로서비스 패턴
- Spring
- Git
- Spring Boot
- 계층형 아키텍처
- spring rest docs
- HTTP 헤더
- 클린코드
- http
- named query
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |