Optional의 개념
Optional의 가장 핵심적인 개념은 null이 올 수 있는 값을 감싸는 Wrapper클래스로써, 참조하더라도 NPE가 발생하지 않도록 도와주는 것입니다.
1. Optional은 null이 아닌 T 타입 참조를 하나 담거나, 아무것도 담지 않을 수 있습니다.
2. Optional은 원소를 최대 1개 가질 수 있는 불변 컬렉션입니다.
Optional 클래스는 아래와 같은 value에 값을 저장하기 때문에 값이 Null이더라도 바로 NPE가 발생하지 않으면서, 클래스이기 때문에 각종 메서드를 제공해 줍니다.
public fianl class Optional<T> {
private final T value;
}
Optional클래스가 제공해주는 중요 메서드
Optional.of(T)
Optional.ofNullable(T);
Optional.empty();
Optional.of(T); → 파라미터로 전달된 값을 Optional로 감싸서 반환한다.(null 불가), null값을 전달하면 NPE를 던진다.
Optional.ofNullable(T); → 파라미터로 전달된 값을 Optional로 감싸서 반환한다.(null 허용)
Optional.empty(); → 비어있는 Optional을 반환해 준다. Optional을 생성해주는 정적 팩토리 메서드이다.
Optional<T>.orElse("기본 값");
Optional<T>.orElseGet("기본 값");
Optional<T>.orElseThrow(Exception::new);
Optional <T>. orElse("기본 값"); → Optional이 비어있는 경우 기본 값을 설정할 수 있습니다. Optional에 값이 있든 없든 무조건 실행됩니다.
Optional <T>. orElseGet("기본 값"); → Optional이 비어있는 경우 기본 값을 설정할 수 있습니다. 새로운 객체를 생성하는 경우에 사용하는 것을 권장합니다.
Optional <T>. orElseThrow(Exception::new); → Optional이 비어있는 경우 Exception을 던집니다. Supplier를 사용해 Optional에 값이 비어있을 때만 새로 생성합니다.
<주의할 점 >
Boxing 된 기본타입(Integer, Long)을 담는 Optional은 값을 두 번 감싸기 때문에 무거운 코드입니다.
그래서 Optionalint, OptionalLong, OptionalDouble 클래스를 제공해 줍니다.
Boxing 된 기본타입을 담는 Optional을 사용하는 일은 줄이는 게 좋습니다.
<장단점>
Optional을 목적에 맞게 올바르게 사용하는 경우
1. Optional을 사용하면 코드가 Null-Safe 해집니다.
2. 가독성이 좋아지고 애플리케이션이 안정적이 됩니다.
Optional을 남발하는 코드
1. 코드의 가독성을 떨어뜨립니다.
2. 시간적, 공간적 비용(or 오버헤드)이 증가합니다.
3. NullPointerException 대신 NoSuchElementException이 발생합니다.
3.1: Optional로 받은 변수를 값이 있는지 판단하지 않고 접근하려고 하는 경우입니다.
3.2: Null-Safe 하기 위해 Optional을 사용했지만, 값의 존재 여부를 판단하지 않고 접근할 때입니다.
4. 이전에는 없었던 새로운 문제들이 발생합니다.
4.1: 기본적으로 Optional은 직렬화를 지원하지 않기 때문에 캐시나 메시지 큐 등과 연동할 때 문제가 발생할 수 있습니다.
<결론>
1. Optional 변수에 null을 할당하면 안 됩니다.
2. 값이 없을 때 Optional.orElseX()로 기본 값을 반환해야 합니다.
3. 단순히 값을 얻으려는 목적으로만 Optional을 사용하면 안 됩니다.
4.생성자, 수정자, 메소드 파라미터 등으로 Optional을 넘기면 안됩니다.
5. Collection의 경우 Optional을 사용하지 말고 빈 Collection으로 처리해야 합니다.
6. 반환 타입으로만 사용해야 합니다.