Optional이란
Java 8에 추가된 null을 보다 편리하게 핸들링 하기 위에 추가된 클래스이다.
null이 올 수 있는 값을 감싸는 Wrapper 클래스로, 참조하더라도 NPE가 발생하지 않도록 도와준다.
Optional 클래스의 메서드
- get: Optional에 있는 값 가져오기
- empty: 빈 Optional 객체
- isEmpty(): Optional에 값이 있는지 없는지 확인하기 (Java 11)
- of: null이 아닌 값으로 Optional 생성 (만약 값이 null이면 NPE가 발생되기 때문에 null이 아님이 확실할 때 사용하는 것이 좋다.)
- ofNullable: null 허용 Optional (null일 수도 있을 때 사용하는 것이 좋다.)
- get: Optional이 같고 있는 값을 반환 (값이 없으면 NoSuchElementException 발생)
- isPresent: 값이 존재하면 true, 빈 Optional 이면 false
- ifPresent: 값이 존재하면 지정된 Consumer를 실행하고, 없으면 아무 동작하지 않는다.
- ifPresentOrElse
Java 9에 추가 되었으며, 추가로 Runnable 인터페이스를 넘겨준다. 값이 존재하면 지정된 Consumer를 실행하고, 없으면 넘겨받은 Runnable을 실행한다.
- or: 값이 존재하면 같은 Optional를 리턴, 없으면 Supplier에서 만든 Optional을 리턴한다.
- orElse: 값이 존재하면 값을 리턴, 없으면 인자로 제공된 기본값을 반환한다. Optional이 감싸고 있는 타입의 인스턴스를 인자로 넘긴다.
-> null이든 아니든 항상 호출된다.
- orElseGet: 값이 존재하면 값을 리턴, 없으면 Supplier에서 제공되는 값을 반환한다.
-> null일 때만 호출된다.
- orElseThrow: 값이 존재하면 값을 리턴, 없으면 Supplier에서 생성한 예외를 발생한다.
- stream: 값이 존재하면 존재하는 값만 포함하는 스트림을 반환하고, 없으면 empty 스크림을 반환한다.
Optional 제대로 사용하기
- Optional은 값을 Wrapping하고 다시 풀고, null일 경우에는 대체하는 함수를 호출하는 등의 오버헤드가 있으므로 성능이 저하될 수 있다. 만약, Optional에 담길 값이 int, long, double과 같이 기본 타입이라면 박싱/언박싱이 사용되는 Wrapper 타입을 사용하지 말고 OptionalInt, OptionalLong, OptionalDouble을 사용하자.
- 새로운 객체를 생성하거나 새로운 연산을 수행하는 경우에는 orElse 보다는 orElseGet을 사용하자. 값이 없으면 orElse()의 인자로서 실행된 값이 반환되므로 의미가 있으나 Optional에 값이 있으면 orElse의 인자로서 실행된 값이 무시되고 버려진다. 이미 생성되었거나 이미 계산된 값일 때만 orElse를 사용하자. orElseGet는 값이 없을 때만 호출되기 때문에 새 객체를 생성하거나 새 연산을 수행해도 불필요한 오버헤드가 없다.
즉, 이미 만들어져있는 상수 같은 것들은 orElse가 적합하고, 동적으로 객체를 만드는 경우에는 orElseGet이 적합하다.
- Optional은 메서드 파라미터/map의 key 타입/인스턴스 필드 타입으로 쓰지 말고, 반환 타입으로만 사용하자. 메서드에 파라미터로 사용할 경우 파라미터에 null이 올 경우 null 체크를 또 해줘야 해서 Optional을 사용하는 의미가 없어진다.
- 리턴 타입이 Optional인 메서드에서 null을 리턴하지 말자. 리턴할 값이 없을 때는 return null 대신 return Optional.empty()를 사용하자.
- Collection, Map, Stream Array, Optional은 그 자체로 이미 비어있는지 아닌지를 판단할 수 있는 컨테이너 성격의 인스턴스들은 Optional로 감싸면 2번 감싸는 것이기 때문에 Optional로 감싸지 말자.
*참고 자료
https://mangkyu.tistory.com/70
http://homoefficio.github.io/2019/10/03/Java-Optional-%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%93%B0%EA%B8%B0/