Optional

이승민·2022년 10월 18일

JAVA8

목록 보기
13/18

Optional 소개

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

  • null을 리턴 && null 체크를 잊는 경우

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

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

Optional

  • 오직 값 한 개가 들어있을 수도 없을 수도 있는 컨테이너

주의할것

  • 리턴 값으로만 쓰기를 권장 (메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드 타입으로 쓰지 말자!)
  • Optional을 리턴하는 메소드에서 null을 리턴하지 말자
  • Collection, Map, Stream, Array, OptionalOptional로 감싸지 말것

Optional API

Optional 만들기

  • Optional.of()
  • Optional.ofNullable()
  • Optional.empty()

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

  • isPresent()
  • isEmpty() (Java 11부터 제공)
List<OnlineClass> springClasses = new ArrayList<>();
        springClasses.add(new OnlineClass(1, "spring boot", true));
        springClasses.add(new OnlineClass(5, "rest api development", false));

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

        boolean present = spring.isPresent();
        System.out.println(present);

Optional에 있는 값 가져오기

  • get()
  • 만약에 비어있는 Optional에서 무언가를 꺼낸다면??
    • 런타임 Exception 계열의 NoSuchElementException 발생 (있는지 확인하고 꺼내야한다.)

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

  • ifPresnet(Consumer)
  • 예) spring으로 시작하는 수업이 있으면 id를 출력
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();

        optional.ifPresent(oc -> System.out.println(oc.getId()));

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

  • orElse(T)
    • 있더라도 메소드가 실행하기는 해야된다.
    • 이미 만들어진 상수같은 것에 사용하기 적합
  • 예) JPA로 시작하는 수업이 없다면 비어있는 수업을 리턴
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();

        OnlineClass onlineClass = optional.orElse(creatNewClass());
    }

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

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

  • orElseGet(Supplier)
    • 있는 경우 메소드 실행X
    • 동적으로 처리해야하는 경우 적합
  • 예) JPA로 시작하는 수업이 없다면 새로 만들어서 리턴하라.
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("jpa"))
                .findFirst();

        OnlineClass onlineClass = optional.orElseGet(App::creatNewClass);

        System.out.println(onlineClass.getTitle());
    }

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

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

  • orElseThrow()
    • NosuchElementException을 던진다.
    • 원하는 에러가 있는 경우 supplier를 쓰면 된다.

Optional에 들어있는 값 걸러내기

  • Optional filter(Predicate)
    • 있다고 가정하고 사용

Optional에 들어있는 값 변환하기

  • Optional map(Function)
  • Optional flatMap(Fuction): Optional 안에 들어있는 인스턴스가 Optional인 경웨 사용하면 편리하다.
 Optional<Progress> progress = optional.map(OnlineClass::getProgress);

        Optional<Progress> progress1 = optional.map(OnlineClass::getProgress);
        Progress progress2 = progress1.orElseThrow();
```![](https://velog.velcdn.com/images/lee2963/post/dd858efd-8948-4d22-9f42-048a5208c1d0/image.jpeg)
profile
💻 끊임없이 성장하는 백엔드 개발자 💻

0개의 댓글