[Java]Optional

윤재열·2022년 2월 15일
0

Java

목록 보기
47/71
post-custom-banner

Optional이란?

값이 있을 수도 없을 수도 있는 컨테이너를 뜻합니다.

  • null이 리턴되어 발생하는 NullPonterException을 방지하고자 나오게 된 개념입니다.
String str = null;
System.out.println(str.indexOf("a")); // NullPointerExecption 발생
  • Method에서 작업 중 반환 값이 제대로 들어오지 않았을 때, 주로 3가지 처리 방법을 사용합니다.
String str = null;

// 방법1. 예외를 던진다 → 에러가 발생하면, stackTrace를 찍는다. 즉, 리소스 낭비이다
if(str == null) {
	throw new IllegalStateException(); // 에러 처리를 강제하게 됨
}
System.out.println(str.indexOf("a"));


// 방법2. 클라이언트 코드에서 null을 확인한다 → 이는 클라이언트에서 놓친다면 에러가 발생할 수 있다
if(str != null) {
	System.out.println(str.indexOf("a"));
}

// 방법3. Optional을 리턴한다 (자바 8부터) → 빈 값이 들어올수도 있음을 클라이언트에게 명시 후, 빈 값인 경우에 대한 처리를 강제한다.
Optional<String> strOptinal = Optional.ofNullable(str);

주의할 점

리턴 값으로만 사용하는 것을 권장합니다.

파라미터로 Optional을 사용하지 않습니다.

-이렇게 되면 Optional을 써서 얻는 메리트가 사라집니다.

  • 파라미터로 Optional을 사용해도 문법적인 오류는 발생하지 않습니다.
  • 하지만, 파라미터 값으로 들어온 null에 ifPresent함수를 호출하려고 할때 NullPointerException이 발생합니다.
  • 결국 Optional 객체 안에 null 이 아닌 값이 들어있는지 확인하는 코드가 필요합니다.
public void setParameter(Optional<Object>param){
if(param != null)
param.ifPresent(p-> this.param = p);
}

Map의 Key 타입으로 Optional을 사용하지 않습니다.

  • Map 인터페이스의 가장 큰 특징 "Null 값을 Key값으로 쓰지 않습니다."
  • Optional을 Key 값으로 사용하여 null이 들어올 수 있다는 것이 Map의 특성을 깨버리는 것이 되어버립니다.

인스턴스 필드 타입으로 Optional을 사용하지 않습니다.

  • 이는 도메인 클래스의 설계 문제입니다.
  • 차라리 상위/하위 클래스로 쪼개거나, deletegation 사용을 권장합니다.
// Optional<Node> node; // 이렇게 사용하지 않는다.

/////////////////////////////////////////
// delegation을 사용한다.
// 참조 객체를 통해 메서드를 호출하는 방식을 사용한다.
Node node = node.getNode();

/////////////////////////////////////////

// Node 클래스에 정의되어 있는 메서드
public Optional<Node> getNode() {
	return Optional.empty();
}

primitive type의 Optional은 따로 존재합니다.

Optional.of(10); // 내부에서 (un)boxing이 이루어진다 → 성능에 좋지 않다.
OptionalInt.of(10); // 각 primitive 타입에 맞는 클래스를 제공하므로 이를 사용하는 것을 권장한다.

Optional을 리턴한다면 null을 반환하지 않습니다.

  • Optional.empty()로 리턴합니다.
public Optional<Object> getParam() {
	// return null; // 이렇게 사용하지 않는다. → getParam 이후 ifPresent() 실행 시, NullPointerException 발생 가능성이 있음
    return Optional.empty(); // null을 담고 있는 Optional 객체를 반환하자.
}

Collection,Map,Stream,Array,Optional은 Optional 로 감싸지 않습니다.

  • 컨테이너 성격의 객체들은 이미 "값이 비어있을 수 있다"라는 의미를 내포하고 있습니다.
  • 해당 객체들을 Optional로 감싸면 Optional을 2번 감싸는 형태가 되므로 무의미 합니다.

Optional API

Optional 만들기

  • Optional.of()
    -인자로서 Null 값을 받지 않는 Optional 객체를 만듭니다.
    -Null 값을 of의 입력으로 받을 시, NullPointerExcoption이 발생합니다.
  • Optional.ofNuallabel()
    -인자로서 Null 값을 허용하는 Optional 객체를 만듭니다.
  • Optional.emptry()
    -Null을 가지고 있는 비어있는 Optional 객체를 만듭니다.

Optional 값 여부 확인하기

  • boolean isPresent()
  • boolean isEmpty() : java 11부터 제공합니다.

Optional 값 가져오기

get()

  • 값이 null일경우 NoSuchElementExceoption 발생
    -가급적 사용하지 않는 것을 추천

ifPresent(Consumer)

  • 값이 있다면 그 값을 가지고 ~를 합니다.
  • 값이 있는 경우만 함수가 동작합니다.

OrElse(T)

  • 값이 있으면 가져오고 없는 경우에 ~를 리턴합니다.
    -값이 있든 없든 orElse안에 T는 실행 됩니다.
    -값이 없을 때, 가져오는 객체가 이미 만들어져 있는 객체인 경우에 적합합니다.

orElseGet(Supplier)

  • 값이 있으면 가져오고 없는 경우에 ~를 리턴합니다.
    -값이 있으면 orElseGet안에 Supplier가 실행되지 않습니다.
    -값이 없을 때, 동적으로 새로운 객체를 생성해 실행해야 하는 경우에 적합합니다.

orElseThrow()

  • 값이 있으면 가져오고 없는 경우에 에러를 던집니다.
    -기본적으로는 NoSuchElementExceoption을 던집니다.
    -Supplier로 원하는 에러를 던지게 설정할 수 있습니다.

Optional 필터

Optional filter(Predicate)

  • Optional에 들어있는 값을 조건에 따라 걸러집니다.
  • 값이 있다는 가정하게 동작합니다.
  • 값이 없다면, 빈 Optional 객체를 반환합니다.

Optional 변환

Optional map(Function)

  • Optional에 들어있는 값을 변환합니다.
    -Optional이 담고 있는 타입이 달라집니다.

Optional flatMap(Function)

-Optional 안에 들어있는 인스턴스가 Optioanl인 경우 사용하면 유용합니다.

// map을 사용한 경우
Optional<Optional<String>> str = optionalOnlineClass.map(OnlineClass::getOptionalString);
Optional<String> optionalString = str.orElse(Optional.empty());

// flatMap을 사용한 경우
Optional<String> optionalStringByFlatMap = optionalOnlineClass.flatMatp(OnlineClass::getOptionalString);

profile
블로그 이전합니다! https://jyyoun1022.tistory.com/
post-custom-banner

0개의 댓글