Optional
- null일 수도있고, 비어있을 수도 있다.
- 메소드에서 작업 중 특별한 상황에서 값을 제대로 리턴할 수 없는 경우 선택할 수 있는 방법
- 예외를 던진다. (비싸다, 스택트레이스를 찍어두니까.)
- null을 리턴한다. (비용 문제가 없지만 그 코드를 사용하는 클리어인트 코드가 주의해야 한다.)
- (자바 8부터)
Optional을 리턴
한다. (클라이언트에 코드에게 명시적으로 빈 값일 수도 있다는 걸 알려주고, 빈 값인 경우에 대한 처리를 강제한다.)
- Optional
오직 값 한개가 들어있을 수도 없을 수도 있는 컨네이너.
- 주의할 것
리턴값으로만 쓰기를 권장
한다. (메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드 타입으로 쓰지 말자.)- Optional을 리턴하는 메소드에서
null을 리턴하지 말자.
-> null 말고 Optional.empty를 리턴하자. - 프리미티브 타입용 Optional을 따로 있다.
OptionalInt, OptionalLong,...
- Collection, Map, Stream Array, Optional은
Opiontal로 감싸지 말 것
. -> 이 자체로 이미 비어있는지 안비어있는지 알 수 있는 컨테이너 성격의 인스턴스들이다.
Optional API
Optional 만들기
- Optional.of()
- Optional.ofNullable()
- Optional.empty()
코드 예시
String name = "hyunwook";
String nullName = null;
Optional<String> myName = Optional.of(name); // null 아닐 때
Optional<String> myName = Optional.empty();// 빈 상자
Optional<String> myName = Optional.ofNullable(name);
Optional<String> myName = Optional.ofNullable(nullName); // null 인지 아닌지 모를때
Optional에 값이 있는지 없는지 확인하기
- isPresent()
- isEmpty() (Java 11부터 제공)
Optional에 있는 값 꺼내오기
get()
- 만약에 비어있는 Optional에서 무언가를 꺼낸다면?? -> NoSuchElementException이 발생한다.
ifPresent(Consumer)
- Optional 이 null 이 아니라면 action 을 실행한다.
Optional<OnlineClass> result = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("jpa"))
.findFirst();
result.ifPresent(oc -> System.out.println(oc.getTitle()));
orElse(T)
- Optional이 null이 아니라면 Optional 안의 값을, null 이라면 T로 공급된 값을 리턴한다.
Optional<OnlineClass> result = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("jpa"))
.findFirst();
// 경우 1
OnlineClass onlineClass = result.orElse("default email");
// 경우 2
OnlineClass onlineClass = result.orElse(createNewClass());
private static OnlineClass createNewClass(){
return new OnlineClass(10, "new class", false);
}
- 경우 1 일때, result 가 null 이 아니라면 해당 값이 추출되고, null 이면 "default email" 이 반환된다.
- 경우 2 일때, null 이든 아니든 createNewClass() 메소드가 호출되면서 새로운 인스턴스가 생성된다. -> 조심해야한다. -> 이럴 경우엔 orElseGet 을 사용하는 것이 바람직하다.
- 정리하면 orElse 일 경우, null 일 경우 반환값이 primitive type 이라면 사용하는것이 바람직하지만, 반환값이 새로운 객체를 생성하는 것이라면 주의 해야서 사용해야 한다.
orElseGet(Supplier)
- Optional 이 Null 이 아니라면 Optional 안의 값을 리턴하고, null 이라면 supplier로 공급되는 값을 리턴한다.
Optional<OnlineClass> result = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("jpa"))
.findFirst();
OnlineClass onlineClass = result.orElseGet(() -> createNewClass());
private static OnlineClass createNewClass(){
return new OnlineClass(10, "new class", false);
}
- 위의 경우 result 가 null 이 아니라면 해당 값이 추출되고, null 인 경우에만 createNewClass() 메소드가 호출되면서 새로운 인스턴스가 생성된다.
orElseThrow()
- Optional에 값이 있으면 가져오고 없는 경우 에러를 던져라.
Optional<OnlineClass> result = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("jpa"))
.findFirst();
OnlineClass onlineClass = result.orElseThrow(IllegalStateException::new);
Optional에 들어있는 값 걸러내기
- Optional filter(Predicate)
Optional<OnlineClass> result = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("jpa"))
.findFirst();
Optional<OnlineClass> onlineClass = result.filter(oc -> !oc.isClosed());
Optional에 들어있는 값 변환하기
- Optional map(Function)
Optional<OnlineClass> result = springClasses.stream()
.filter(oc -> oc.getTitle().startsWith("jpa"))
.findFirst();
Optional<Integer> integer = result.map(OnlineClass::getId);
- Optional flatMap(Function): Optional 안에 들어있는 인스턴스가 Optional인 경우에 사용하면 편리하다.
- 반환값이
Optional<Optional<Progress>>
일 경우에 사용하면 편리하다. -> 한겹을 까준다.
- 반환값이
REFERENCES
- https://wickso.me/java/difference-between-orelse-and-orelseget-in-optional/
- 백기선님의 더 자바, Java 8
'Java' 카테고리의 다른 글
Stream (0) | 2022.02.26 |
---|---|
Static 변수와 Static 메서드 (0) | 2022.02.26 |
Object 클래스 (0) | 2022.02.26 |
Exception (0) | 2022.02.26 |
Class 클래스 (0) | 2022.02.26 |