리팩토링 5탄(Optional)

Moon·2024년 3월 8일
0
post-thumbnail

이번 리팩토링은 자바8부터 도입되어 사용되고 있는 Optional을 활용해 리팩토링을 진행했습니다.

자바 병렬 프로그래밍을 작성했던, 브라이언 게츠의 말을 빌려 좋은 Optional과 주의해야할 Optional에 대해 정리해보았습니다


  1. Optional이란(feat.NPE)
  • 자바8부터 Optional 클래스가 새로 등장했다.
  • Optional은 NPE(NullPointerException)이 발생하는 것을 방지한다.
  • null이 될 수 있는 값을 감싸주는 콘테이너 클래스다.
  • 값이 존재 하지 않다면, NPE가 발생하는 것이 아닌 Optional 클래스는 '값이 없음'을 알려준다
public final class Optional<T> {

    /**
     * If non-null, the value; if null, indicates no value is present
     */
    private final T value;

  1. Optional 사용 이전
  • null 처리를 해주지 않으면 다음과 같이 NPE가 발생할 수 있다.
package refactoring5;

public class CheckNullPointException {

    public static void main(String[] args) {

        Animal myAnimal = new Animal();
        String myAnimalName = myAnimal.getName();

        if(myAnimalName.length() == 3){
            System.out.println("세글자다!");
        } else {
            System.out.println("아니다!");
        };
    }
}

  • 자바8 이전까지는 다음과 같은 처리가 필요했다.
        if(myAnimalName != null){
            // ... 로직 처리
        }

  1. Optional 사용 이후
  • Optional을 사용하여, 만약 이름이 존재하지 않다면 "NoName"을 출력하도록 작성할 수 있다

        String myAnimalName = Optional.ofNullable(myAnimal.getName())
                .orElseGet(()-> "NoName");


  1. Optional의 method 살펴보기
  • orElse() 와 orElseGet()
    orElse()의 경우 Optional에 해당하는 값이 null인 경우 파라미터로 입력된 other가 실행된다
        String myAnimalName = Optional.ofNullable(myAnimal.getName()).orElse("내꺼");
        String yourAnimalName = Optional.ofNullable(myAnimal.getName()).orElseGet(()->"너꺼");

        System.out.println("내 애니멀은 : " + myAnimalName);
        System.out.println("너 애니멀은 : " + yourAnimalName);

내 애니멀은 : 내꺼
너 애니멀은 : 너꺼

orElseGet() 메서드를 살펴보면 Supplier 인자를 받고 있고, 이는 함수형 인터페이스인 람다식을 매개변수로 받는 것이다.

    /**
     * If a value is present, returns the value, otherwise returns the result
     * produced by the supplying function.
     *
     * @param supplier the supplying function that produces a value to be returned
     * @return the value, if present, otherwise the result produced by the
     *         supplying function
     * @throws NullPointerException if no value is present and the supplying
     *         function is {@code null}
     */
    public T orElseGet(Supplier<? extends T> supplier) {
        return value != null ? value : supplier.get();
    }

orElse()를 사용할 시 주의할 점은, Optional 인자가 null이 아니어도 무조건 실행된다.
출력된 결과를 통해 이를 확인할 수 있다.

        // 무조건 실행되는 orElse()
        Animal hisAnimal = new Animal();
        hisAnimal.setName("초코");

        String hisAnimalName = Optional.ofNullable(hisAnimal.getName()).orElse(checkPlay());

        System.out.println("그의 애니멀은 : " + hisAnimalName);

NULL이 아니더라도 무조건 실행
그의 애니멀은 : 초코


  1. Optional에 대한 Brian Goetz의 한 마디(feat.stackoverflow)

우리의 의도는 "결과 없음"을 표현할 명확한 방법이 필요한 라이브러리 메서드 반환 유형에 제한된 메커니즘을 제공하는 것이었습니다.
그러한 유형에 null을 사용하는 것은 오류를 유발할 가능성이 압도적으로 높았습니다.


  1. Optional 사용 시 주의사항(feat.Brian Goetz)

    NEVER call Optional.get unless you can prove it will never be null; instead use one of the safe methods like orElse or ifPresent

  • get()을 통해 직접 값을 꺼내오지 말고, orElse() 또는 ifPresent()등을 활용하여 처리하도록 하자
  • Optional 변수에 null을 할당하지 말자. 그렇게 되면 Optional 자체가 null인지 검사해야한다. Optional.empty()를 사용하자.
  • 좋은 예시(https://mangkyu.tistory.com/70)

참고자료
1. [Java] Optional이란? Optional 개념 및 사용법 - (1/2)
2. 브라이언 게츠의 스택오버플로우 답변
3. Optional 클래스

profile
안녕하세요. Moon입니다!

0개의 댓글