-
[더 자바8] Opitonal 소개JAVA/JAVA8 관련 2022. 4. 5. 22:24
Optional 소개
자바 프로그래밍에서 NullPointerException을 많이 보게 됨.
-> null을 리턴하거나 Null 체크를 빼먹었기 때문임.
메소드에서 작업 중 특별한 상황에서 값을 제대로 리턴할 수 없는 경우 선택할 수 있는 방법
1. 예외(throw)를 던진다.
단점 : 리소스 소모가 많이 됨.
2. null을 리턴한다.
단점 : 비용 문제가 없지만, 그 코드를 사용하는 Client 코드가 주의해야 한다.
3. (자바 8 ~) Optional을 리턴한다.
(클라이언트에 코드에게 명시적으로 빈 값일 수도 있다는 걸 알려주고, 빈 값인 경우에 대한 처리를 강제한다.)
Optional
: 오직 값 한 개가 들어있을 수도 없을 수도 있는 컨네이너.
주의할 것
- 리턴값으로만 쓰기를 권장 (메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드 타입으로 쓰지 말자.)
- Optional을 리턴하는 메소드에서 null을 리턴하지 말기.
- 프리미티브 타입용 Optional을 따로 있다. OptionalInt, OptionalLong (비용적으로 이득)
- Collection, Map, Stream Array, Optional 등은 Opiontal로 감싸지 말 것.
예제
public class OnlineClass { private Integer id; private String title; private boolean closed; // 비권장 //public Optional<Progress> progress1; public Progress progress; public OnlineClass(Integer id, String title, boolean closed) { this.id = id; this.title = title; this.closed = closed; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public boolean isClosed() { return closed; } public void setClosed(boolean closed) { this.closed = closed; } /** * 아래와 같이 쓰면 오히려 Null체크를 한번 더해야되서 Optional을 쓰는 의미도 없고 코드만 번거러워짐. public void setProgress(Optional<Progress> progress) { if(progress != null) { progress.ifPresent(p -> this.progress. =p;); } } **/ public Optional<Progress> getProgress() { // Null체크 방지를 위해 아래와 같이도 사용 가능하지만 Resource 낭비가 심함. /* if(this.progress == null) { throw new IllegalStateException(); }*/ return Optional.ofNullable(progress); // Null return하고 싶을 시 // return Optional.empty(); } }
public class Progress { private Duration studyDuration; private boolean finished; public Duration getStudyDuration() { return studyDuration; } public void setStudyDuration(Duration studyDuration) { this.studyDuration = studyDuration; } }
public class App { public static void main(String[] args) { List<OnlineClass> springClasses = new ArrayList<>(); springClasses.add(new OnlineClass(1, "spring boot", true)); springClasses.add(new OnlineClass(5, "rest api development", false)); // 1. 아래와 같이 객체를 생성하고 studyDuration을 찍으면 NullPointException이 발생한다. // 그 이유는 progress가 Null이기 때문에 이러한 NullPointException을 방지하기 위해서 Optional 사용 /** OnlineClass spring_boot = new OnlineClass(1,"spring boot", true); Duration studyDuration = spring_boot.getProgress().getStudyDuration(); // Optional을 사용하지않으면 아래와 같이 null 아닐대 조건문 필요 if(spring_boot.getProgress() !=null) { System.out.println(studyDuration); } **/ // primitive type (기본형 타입)의 경우 Boxing unBoxing이 내부적으로 벌어지기 떄문에 2번처럼 사용하는걸 권장한다. //1 //Optional.of(10); //2 //OptionalInt.of(10); } private static OnlineClass createNewClasss() { System.out.println("creating new online class"); return new OnlineClass(10, "New class", false); } }
'JAVA > JAVA8 관련' 카테고리의 다른 글
Date 와 Time 소개 (0) 2022.05.15 Optional API 사용 (0) 2022.04.17 [더 자바8] STREAM API (0) 2022.03.20 [더 자바8] 인터페이스 기본 메소드와 스태틱 메소드 (0) 2022.02.13 [더 자바 8] 메소드 레퍼런스 (0) 2022.02.13