5부 Optional
1. Optional 소개
getProgress의 StudyDuration(공부 시간)을 출력하려고 시도하다가 NullpointException이 발생한 상황이다.
public Progress progress;
public OnlineClass(Integer id, String title, boolean closed) {
this.id = id;
this.title = title;
this.closed = closed;
}
그 이유는 OnlineClass의 progress값이 Null이기 때문이다.
그래서 Null의 메서드를 호출하려고 했기 때문에 Null을 참조하는 과정에서 에러가 발생했다.
OnlineClass spring_boot = new OnlineClass(1, "spring boot", true);
Progress progress = spring_boot.getProgress();
if ( progress != null) {
System.out.println(progress.getStudyDuration());
}
이런 코드의 문제점은 에러를 발생시키기 좋다는 것이다.
자바 프로그래밍에서 NullPointerException을 종종 보게 되는 이유
● null을 리턴하니까! && null 체크를 깜빡했으니까!
메소드에서 작업 중 특별한 상황에서 값을 제대로 리턴할 수 없는 경우 선택할 수 있는 방법(자바 8 이전의 상황)
1. 예외를 던진다. (비싸다, 스택트레이스를 찍어두니까.)
public Progress getProgress() {
if (this.progress ==null){
throw new IllegalStateException();
}
return progress;
}
2. null을 리턴한다. (비용 문제가 없지만 그 코드를 사용하는 클리어인트 코드가 주의해야 한다.)
public Optional<Progress> getProgress() {
return Optional.ofNullable(progress);
}
● (자바 8부터) Optional을 리턴한다. (클라이언트에 코드에게 명시적으로 빈 값일 수도 있다는 걸 알려주고, 빈 값인 경우에 대한 처리를 강제한다.)
Null일수도 있는 값이면 ofNullable 사용.
Optional.of(..)는 파라미터값이 반드시 null이 아닐경우에만 사용 가능.
Optional
● 오직 값 한 개가 들어있을 수도 없을 수도 있는 컨네이너.
주의할 것
● 리턴값으로만 쓰기를 권장한다. (메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드 타입으로 쓰지 말자.)
1. 메서드 매개변수 Optional 예제
spring_boot.setProgress(null);
public void setProgress(Optional<Progress> progress) {
if(progress != null) {
progress.ifPresent(p -> this.progress = p);
}
}
호출하는쪽에서 얼마든지 null을 넣을 수 있다.
그러면 null의 ifPresent함수를 실행하므로 NullpointException이 발생하고, 한번더 null체크를 해야 한다.
2. Map Optional
Map의 특징 중 하나는 key값이 null일 수 없다는 것이다.
그런데 Optional을 사용하면 key값이 비어있을 수도, 아닐 수도 있다는 의미가 되므로 좋지 않다.
● Optional을 리턴하는 메소드에서 null을 리턴하지 말자.
Null을 리턴하도록 코드를 구성하면 ifPresent를 사용하다가 NullpointException이 발생하게 된다.
return Optional.empty();
정말 리턴할 값이 없다면 empty를 사용하자.
● 프리미티브 타입용 Optional을 따로 있다. OptionalInt, OptionalLong,...
Optional.of(10);
이런식으로 넣을 수는 있으나, 이렇게 되면 박싱, 언박싱이 발생하는 문제가 있다. -> 성능저하
OptionalInt.of(10);
이런식으로 추천.
● Collection, Map, Stream Array, Optional은 Opiontal로 감싸지 말 것.
(컨테이너 성격의 인스턴스를 감싸지 말라는 뜻)
참고
● https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
● https://www.oracle.com/technical-resources/articles/java/java8-optional.html
● 이팩티브 자바 3판, 아이템 55 적절한 경우 Optional을 리턴하라.
'스프링 스터디 (인프런) > 더 자바 8' 카테고리의 다른 글
섹션 5. Date와 Time - Date와 Time 소개 (0) | 2023.04.26 |
---|---|
섹션 4. Optional-Optional API (0) | 2023.04.24 |
Stream - Stream API (0) | 2023.04.14 |
Stream - Stream 소개 (0) | 2023.04.09 |
인터페이스의 변화 - 자바 8 API의 기본 메소드와 스태틱 메소드 (0) | 2023.04.08 |