Language/Java

[Java] 개발자라면 알아야 할 Optional class?!

ABCD 2023. 4. 11.

Optional 이란??

  • 우선 Optional을 왜 사용하게 되었는지부터 알아야 한다.
    • Optional은 NPE(NullPointerException)을 피하기 위해 사용한다.

 

public final class Optional<T> {
  //If non-null, the value; if null, indicates no value is present
  private final T value;
  
  ...
}

 

Optional 생성

 

Optional.empty() - 값이 null인 경우

  • Optional은 Wrapper 클래스이기 떄문에 값이 없을수도 있는데, 이때 생성하는 방법
Optional<String> optional = Optional.empty();
  • Optional 클래스 내부에서 static 변수로 객체를 생성해서 미리 가지고 있기 때문에 빈 객체를 여러번 생성해줘야 하는 경우에도 하나의 객체를 공유함으로써 메모리를 절약한다.
public final class Optional<T> {

  private static final Optional<?> Sample = new Optional<>();
  private final T value;
  
  private Optional() {
    this.value = null;
  }

  ...

}

 

Optional.of() - 값이 non-null인 경우

  • 해당 데이터가 어떤한 경우에도 null이 아닌경우 사용
// Optional의 value는 절대 null이 아니다.
Optional<String> optional = Optional.of("MyName");

 

Optional.ofNullbale() - 값이 Null일수도, 아닐수도 있는 경우

  • 어떤 데이터가 올지 모를 때 사용
  • null도 가능하고 non-null도 가능
  • 이 후 orElse() or orElseGet() 메서드를 이용하여 어떤한 경우에도 안전하게 값을 가져 올 수 있다.
Optional<String> Sample = Optional.ofNullable(getContent());
String Content = Sample.orElse("anonymous");  //해당 값이 null일 경우 anonymous를 리턴

[Practice]

1. java8 이전 버전과 java8 이후 버전과 비교

// Java8 이전
List<String> names = getNames();
List<String> tempNames = list != null 
    ? list 
    : new ArrayList<>();

// Java8 이후
List<String> nameList = Optional.ofNullable(getNames())
    .orElseGet(() -> new ArrayList<>());

 

2. 조건문을 통해 null을 피하는 방법과 Optional을 이용한 방법 비교

//조건문을 사용한 null처리 방법
public String findPostCode() {
  UserVO userVO = getUser();
  if (userVO != null) {
    Address address = user.getAddress();
    if (address != null) {
      String postCode = address.getPostCode();
      if (postCode != null) {
        return postCode;
      }
    }
  }
  return "우편번호 없음";
}

//Optional을 이용한 null처리 방법
public String findPostCode() {
  Optional<UserVO> userVO = Optional.ofNullable(getUser());
  Optional<Address> address = userVO.map(UserVO::getAddress);
  Optional<String> postCode = address.map(Address::getPostCode);
  String result = postCode.orElse("우편번호 없음");

  // 그리고 위의 코드를 다음과 같이 축약해서 쓸 수 있다.
  String result = user.map(UserVO::getAddress)
    .map(Address::getPostCode)
    .orElse("우편번호 없음");
}

 

3. 이름을 대문자로 변경하는 코드에서 NPE처리

//try-catch문을 사용한 방법
String name = getName();
String result = "";

try {
    result = name.toUpperCase();
} catch (NullPointerException e) {
    throw new CustomUpperCaseException();
}

//Optional을 이용한 방법
Optional<String> nameOpt = Optional.ofNullable(getName());
String result = nameOpt.orElseThrow(CustomUpperCaseExcpetion::new)
                  .toUpperCase();

Optional 마무리

  • NPE을 처리하기 위해 등장한 Warrper 클래스
  • null일 경우 처리하는 함수를 호출하는 등 Cost가 많이 드는 경우 성능이 저하되므로 절대 Null이 아니라면 사용을 지양
  • 결과가 null일 수 있고, null에 의해 오류가 발생 할 수 있을 때 사용

 

728x90
반응형

댓글

💲 추천 글