자바 - Optional

SeungTaek·2021년 8월 25일
0

자바(Java)

목록 보기
5/8
post-thumbnail

본 게시물은 스스로의 공부를 위한 글입니다.
틀린 내용이 있을 수 있습니다.

📒 Optional은 왜 사용할까?

📌 NullPointerException이 종종 발생되는 원인

  1. 개발자가 null체크를 깜빡한다.
  2. 함수에서 null을 리턴한다.

📌 메소드에서 정상적인 값을 리턴할 수 없는 경우 선택할 수 있는 방법

  1. 예외를 던진다.
    • 스택 트레이스를 찍기 때문에 그만큼 resource를 소모하는 작업이다.
  2. null을 리턴한다.
    • 그 메소드를 사용하는 클라이언트에서 체크를 계속해야 한다.
  3. Optional을 리턴한다.
    • 명시적으로 빈 값일 수도 있다는 것을 알려주자.



📒 Optional이란?

  • T타입 객체의 래퍼클래스.
  • 모든 타입을 저장할 수 있다.
  • null을 직접 다루기는 위험하기 때문에 간접적으로 다루기
  • 기존에는 null 체크를 하려면 if를 사용해야 하는데, 코드가 지저분해진다. 하지만 Optional을 사용하면 코드가 깔끔해짐.

📌 주의할 점

  1. 리턴값으로만 쓰기를 권장

    • 매개변수, 맵의 키, 인스턴스 필드 등의 타입으로 사용하지 말자.
  2. Optional을 리턴하는 메소드에서 null을 리턴하지 말자.

    • Optional을 쓰는 이유가 없어진다. 정말 리턴할게 없다면 Optional.empty()리턴
  3. 기본형 타입용 Optional이 따로 있다.(OptionalInt, OptionalLong , OptionalDouble)

    • 박싱, 언박싱의 불필요한 작업을 줄일 수 있다.
    • 성능상의 이유로 사용
    • API 이름이 살짝 달라진다.
  4. Collection, Stream, Optional은 Optional로 감싸지 말 것.

    • 그 자체로 이미 null일 수 있다는 의미를 내포하는데, 굳이 또 Optional을 감쌀 필요가 없다. 2번 감싸는 꼴이 되버림.



📒 Optional API

🎈 Optional 만들기

Optional.of(객체)
Optional.of(null) //NullPointerException 발생
Optional.ofNullable(null) //가능
Optional.empty()

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

  • isPresent()

    • null이면 false, 아니면 true 리턴
  • isEmpty() (자바 11부터 제공)

if(optional.isPresent()){
	System.out.println("값이 있습니다.");
}
if(optional.isEmpty()){
	System.out.println("값이 없습니다.");
}

🎈 Optional에 있는 값 가져오기

  • get()
  • 비어 있는 Optional이라면 NoSuchElementException 발생
  • 그렇기 때문에 get() 사용은 지양한다.
Optional<String> optional = Optional.of("Optional입니다.");
String str = optional.get();

🎈 Optional에 값이 있는 경우 그 값으로 ~을 해라

  • ifPresent(Consumer)
optional.ifPresent(oc -> System.out.println(oc.getTitle()));

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

  • orElse(T), orElseGet(Supplier)
  • ifPresent로 하기에는 할 작업량이 많아서, 무조건 값을 꺼내야 하는 경우에 사용.
  • 사실 값이 있더라도, ( )내에 있는 작업은 무조건 실행된다. (리턴이 안되는것 뿐)
  • 따라서 orElseGet을 사용한다. (아래 참고)
OnlineClass onlineClass=optional.orElse(new OnlineClass()); //값이 있든 없든 객체 생성은 된다.
OnlineClass onlineClass=optional.orElseGet(()->new OnlineClass()); //값이 있으면 Supplier이 실행되지 않는다.

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

  • orElseThrow()
OnlineClass onlineClass=optional.orElseThrow(IllegalStateException::new)

🎈 Optional에 들어있는 값 걸러내기

  • Optional filter(Predicate)
  • 값이 있다는걸 가정하고 실행.
  • 리턴값이 false면 버리고, true면 다음거 실행
Optional<OnineClass> op=optionals.stream()
    .filter(oc -> oc.getTitle().startWith("spring"))
    .findFirst();

🎈 Optional에 들어있는 값 변환하기

  • stream map과 마찬가지로, 값을 내가 원하는 형태로 변환할 수 있다.

  • Optional map(Function)

//Optional<OnlineClass>를 Optional<Integer>로 바꿀 수 있다.
Optional<Integer> integer=optional.map(OnlineClass:getId);
  • Optional flatMap(Function)
    • Optional의 객체들을 쫙 나열해서 명령들 실행.
    • Optional 안에 들어있는 인스턴스가 Optional인 경우에 사용하면 편리하다.
    • 값이 없으면 Optional.empty 반환

🎈 OptionalInt 등의 기본형 래퍼 클래스

  • 성능상의 이유로 사용
  • 사용법은 일반적인 optional과 비슷하다.
OptionalInt opt=OptionalInt.of(0); //0을 저장
OptionalInt opt2=OptionalInt.empty(); //0을 저장
opt.isPresent(); //true
opt2.isPresent(); //false
opt.equals(opt2); //false

Reference

자바의 정석
인프런 더 자바(백기선)

profile
I Think So!

0개의 댓글