반응형

Optional 문법에 대해서는 설명하지 않는 글이다. 아주 간단하기 때문에 문법은 찾아보길 바란다.

Optional전에 null은 어떻게 처리했을까?


null을 반환할지 안할지 모른다.

하지만 Optional을 반환하면, nullable을 알 수 있다.

null 체크를 깜박할 수 있다.

nullable을 알 수 있기 때문에 깜빡하지 않는다.

null를 반환하는 것 자체가 문제다.

null을 반환하지 않으면, 예외를 던지는 방법도 있다.
null 반환, 예외 반환 딱 2개 뿐이었다.

null을 반환하면, NPE가 발생할 수 있고, 클라이언트가 직접 처리해야 한다.

예외 던지기

예외를 던지면 클라이언트가 null 처리를 안해도 되기 때문에 편하긴 하지만,
checkedException을 던질 경우 강제로 예외를 처리해야 하는 번거로움이 있고,
예외 발생 시 자바는 stackTrace를 실행하기 때문에 불필요한 리소스를 사용하게 된다.
즉, 진짜 필요할 때 예외를 던져야 하고, 무분별하게 예외를 던지는 것은 null 처리일 경우가 아니어도,
좋은 습관은 아니다.

Optional을 사용하면 위의 문제를 어떻게 해결할까?


Optional은 nullable한 Wrapper 클래스이다. 그뿐이다.
null 처리를 조금 더 편리하게 하기 위해 기능을 제공하고, 명시적으로 nullable을 표현한다.

Optional 사용 시 주의 사항


리턴값으로만 사용하기를 권장한다.

파라미터, Map key, 필드 타입으로 권장하지 않는다.
쓸 수는 있다. 하지만 권장하지 않는 이유를 아래에서 알아보자.

문제점을 알아보자.

**파라미터로 Optional 사용하지 말자.**

회사에서 Optional을 많이 쓰면서 동일한 실수를 했었다. 아래 코드는 학생의 취미를 수정하는 코드이다.

import java.util.Optional;

public class Student {

    private String name;
    private String hobby = "취미 없음";

    public Student(String name) {
        this.name = name;
    }

    public void updateHobby(Optional<String> hobby) {
        // 방법 1
        if (hobby.isPresent()) {
            this.hobby = hobby.get();
        }

        // 방법 2
        hobby.ifPresent(s -> this.hobby = s);
    }
}

파라미터로 Optional을 받았다. 이 경우 코드처럼 두 가지 방법으로 처리할 수 있다.
이게 무슨 문제가 될까? 바로 NPE가 발생할 수 있다.

아래 코드로 살펴보자.

class Main {

    public static void main(String[] args) {
        Student student = new Student("더기");
        student.updateHobby(null);
    }
}

바로 문제는 null을 넘길 수 있다는 것이다. Optional이 넘어온게 아니라 null이 넘어온 것이다.

하지만 NPE를 방지할 수는 있다. 아래 코드를 살펴보자.

public void updateHobby(Optional<String> hobby) {
    if (hobby != null) {
        hobby.ifPresent(s -> this.hobby = s);
    }
}

결국 Optional을 쓰는 의미가 전혀없고, 더 복잡해지기만 하는 코드가 만들어진다.

**Map의 Key타입으로 Optional을 사용하지 말자.**

Map의 특성을 깨트리는 것이다. Map의 Key 특성은 Key는 null이 아닌 것이다.
하지만 Optional을 쓴다는 것이 이를 위반하게 된다.

**인스턴스 필드 타입으로 Optional 사용하지 말자.**

이 부분은 아직 공감은 가지 않는다.
그래도 이유는 엔티티 설계상의 문제라고 한다. 상위 클래스나 delegate를 사용하기를 권장한다고 한다.

Optional에 Null을 반환하지 말자.

위의 문제와 같이 Optional 자체가 null이기 때문에 NPE를 발생시킨다.
Optional.empty()를 반환하자.

이건 내가 이펙티브 자바를 잘못 이해를 했던 부분이다. 이펙티브 자바에도 동일한 내용이 있는데
이를 orElse(null)을 지양하라는 의미로 받아들였다. 하지만 실제로 회사에서 코드를 작성할 때 null이 필요한 경우가
있었는데 다른 의미였다. Optional<T> optional = null; 을 하지 말라는 의미였다.

Primitive 타입용 Optional은 따로 있다.

OptionalInt, OptionalLong …이 있다.
그냥 Optional을 사용하게 되면 박싱 언박싱이 일어나기 때문에 성능상 안좋다.

Container, Collection등은 Optional을 사용하지 말자.

Collection, Map 등과 같이 그 자체가 비어있는지 판단을 할 수 있는 것들은
Optional로 감싸도 전혀 의미가 없다.

성능상의 문제

아무래도 박싱 언박싱이 일어나기 때문에 성능상 문제를 발생시킬 수 있다.
그러한 경우는 차라리 null을 반환하거나 예외를 던지는 편이 효과적을 수 있다.

반응형

'Java' 카테고리의 다른 글

Java static과 클래스 로드 및 초기화  (0) 2022.08.28
JDBC란 무엇인가?  (0) 2022.08.17
CountDownLatch로 동시성 테스트 하기  (0) 2022.05.14
Java Comparator, Comparable  (0) 2022.02.22
리플렉션으로 DI 컨테이너 만들기  (0) 2021.12.21
복사했습니다!