티스토리 뷰

스프링, 자바

Optional

killog 2021. 4. 9. 21:16
반응형

Optional 소개

🔍 자바 프로그래밍에서 NullPointerException 을 종종 보게되는 이유

​ ➡➡ null 을 리턴했는데,null 체크를 까먹었으니까!

💡 메소드에서 작업 중, 특별한 상황에서 값을 제대로 리턴할 수 없는 경우 선택할 수 있는 방법

  • 예외를 던진다.(비싸다. 스택 트레이스를 찍으니까)
  • null 을 리턴한다.(비용문제는 없지만, 그 코드를 이용하는 클라이언트 코드가 주의해야함)
  • (자바 8부터) Optional 을 리턴한다.(클라이언트 코드에게 명시적으로 빈 값일 수 있음을 알려주고, 빈 값인 경우에대한 처리를 강제해버림)

Optional

  • 오직 값 한 개가 들어있거나 없을 수 있는 컨테이너( 1 or 0 )

null 일수도 있는 값은 Nullable 로 감싸야한다.

public Optional<Progress> getProgress(){
    return Optional.ofNullable(progress);
}

주의할 것

  • 리턴값으로만 쓰기 권장 (메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드 타입으로 쓰지 말 것)
  • Optional을 리턴하는 메소드에서 null 을 리턴하지 말자.
  • 프리미티브 타입용 Optional 은 따로 있다. OptionalInt, OptionalLong...
  • Collection, Map, Stream Array, Optional 은 Optional 로 감싸지 말 것

Optional 2

Optional 만들기

  • Optional.of()
  • Optional.ofNullabel()
  • Optional.empty()

Optional 에 값이 있는지 없는지 확인하기

  • isPresent()
  • isEmpty() (Java 11 부터 제공)

Optional 에 있는 값 가져오기

  • get()
  • 만약에 비어있는 Optional 에 무엇인가를 꺼낸다면?

Optional 에 값이 있는 경우, 그 값을 가지고 ~ 를 하라.

  • ifPresent(Consumer)
  • 예) Spring 으로 시작하는 수업이 있으면 id 를 출력하라.

Optional 에 값이 있으면 가져오고 없는 경우, ~ 를 리턴

// 실제 있다고 해도 orElse 내부 코드는 실행이 된다.

  • orElse(T)
  • 예) JPA 로 시작하는 수업이 없다면, 비어있는 수업을 리턴하라.

Optional 에 값이 있으면 가져오고 없는 경우 ~ 를 하라.

  • orElseGet(Supplier)
  • 예) JPA 로 시작하는 수업이 없다면 새로 만들어서 리턴하라.

Optional 에 값이 있으면 가져오고 없는 경우 에러를 던져라.

  • orElseThrow()

Optional 에 들어있는 값 걸러내기

  • Optional filter(Predicate)

Optional 에 들어있는 값 변환하기

  • Optional map(Function)
  • Optional flatMap(Function): Optional 안에 들어있는 인스턴스가 Optional 인 경우 사용하면 편리하다.

실습

package me.whiteship.java8to11;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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));

        Optional<OnlineClass> optional = springClasses.stream()
                .filter(oc -> oc.getTitle().startsWith("spring"))
                .findFirst();

        // orElse : 이미 만들어진 상수 같은것에 적합
        OnlineClass onlineClass = optional.orElse(createNewClasss());
        System.out.println("onlineClass.getTitle() = " + onlineClass.getTitle());


        // orElseGet : 동적 추가 작업에 적합
        OnlineClass onlineClass1 = optional.orElseGet(App::createNewClasss);

        // orElseThrow: 없으면 에러
        OnlineClass onlineClass2 = optional.orElseThrow(()->{return new IllegalArgumentException();});
        OnlineClass onlineClass3 = optional.orElseThrow(IllegalAccessError::new);


        // isEmpty  , isPresent
        Optional<OnlineClass> onlineClass4 = optional.filter(o -> !o.isClosed());
        System.out.println("onlineClass4.isEmpty() = " + onlineClass4.isEmpty());
        System.out.println("onlineClass4.isPresent() = " + onlineClass4.isPresent());

        // flatMap : 양파 깔때 사용
        Optional<Progress> progress = optional.flatMap(OnlineClass::getProgress);
        // flatMap is Same as
        Optional<Optional<Progress>> progress1 = optional.map(OnlineClass::getProgress);
        Optional<Progress> progress2 = progress1.orElseThrow();
    }

    private static OnlineClass createNewClasss() {
        System.out.println("creating new online class");
        return new OnlineClass(10, "New class", false);
    }


}




참고 문헌

https://docs.google.com/document/d/1UxKM56um1mjGeayxmJmvALM5CDIJC17vx1-sDwoEbSs/edit

반응형

'스프링, 자바' 카테고리의 다른 글

DB Connection Pool  (0) 2021.04.23
자바의 Stream API  (0) 2021.04.09
AspectJ 과 Spring AOP  (0) 2021.03.29
Log4j 레벨 간단 정리  (0) 2021.03.29
Dispatcher-Servlet  (0) 2021.03.04
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
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 29 30
글 보관함