JAVA

JAVA의 Optional 정리 (Java 8 기준)

Ambitions 2021. 3. 22. 15:05

오늘은 Java의 Optional에 대해서 정리해보려고 한다.

Optional class는 Java 8 부터 도입된 클래스로 공식 API 설명에 따르면 "null이 아닌 값을 포함하거나 포함하지 않을 수있는 컨테이너 객체" 라고 한다. 

마이바티스나 아이바티스를 쓴다거나 Java 8버전 이하로 개발을 한다면 익숙해지기 어려운 개념인 것 같은데, 나의 경우는 회사에서 JPA를 사용하고 있고, Spring JPA의 JpaRepository의 findOne, findById.. 등의 결과 값이 Optional로 돌아오기 때문에 익숙해질 수 밖에없다.

여기서는 내가 주로 사용하는 Optional의 메소드만 코드로 정리 할 예정이고, 이외의 메소드는 아래표나 공식 문서를 참조하는 것이 좋을 것 같다. (아래 표도 번역기 + 내가사용한 경험으로 의역한 것...)

메서드 설명
empty() 빈 optional 객체를 리턴
equlas(Object obj) 두 개체가 같은지 비교
filter(Predicate<? super T> predicate) 값이 존재하고, 주어진 조건이 맞다면 리턴 아니면 빈 값
flatMap(Function<? super T,Optional<U>> mapper) 값이 존재하면, 매핑 한 값을 리턴(Optional 형이아님)
get() 값이 존재하면 해당 값을 리턴 없을 경우 예외발생
hashCode() 값이 있는 경우 해시 코드 값을 리턴, 없는 경우 0
ifPresent(Consumer<? super T> consumer) 값이 있는 경우 작성된 기능을 실행 없을 경우 실행X
isPresent() 값이 있는경우 true 없는경우 false
map(Function<? super T,? extends U> mapper) 값이 있으면 제공된 매핑 함수를 적용하고 결과가 null이 아니면 결과를 Optional자료형으로 리턴. (안써봐서 잘모름)
of(T value) Optional 값을 바로 리턴(null이 아니라는 가정)
ofNullable(T value) Optinal의 값이 null 일수도 있으면 해당 값을 리턴
orElse(T other) Optional의 값이 있으면 값을 전달 아닌 경우 처리된 케이스 전달
orElseGet(Supplier<? extends T> other) 값이 있는 경우 값 전달 없으면 Other 처리된 부분을 전달
orElseThrow(Supplier<? extends X> exceptionSupplier) 값이 있는경우 값 전달, 없는 경우 throw된 부분 수행
toString() 값이 있는 경우 문자열로 전달

Java 8버전 기준으로 위 표와 같은 메서드들이 있는데, 기본적으로 Optional에서 핵심은 Optional의 null값 체크라고 생각한다. 여기서 내가 주로 사용하는 메서드들은 toString, orElseThrow, hasCode, equals, empty를 제외하고 나머지들을 사용하는데, 나의 경우 다음과 같이 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Test {
 
    @Autowired
    MemberRepository membeRepo;
 
    public void optionalTest(Long id) {
        //보통 사용하는 패턴(Optional을 바람직하게 쓰는 건 아니라고 한다)
        Optional<Member> member = membeRepo.findById(id);
        if (member.isPresent()) {
            System.out.println(member.get().getName());
        }
        //위의 isPresent는 ifPresent를 이용해 다음과 같이 바꿀 수 있음
        member.ifPresent(m -> System.out.println(m.getName()));
 
        //of는 Optional값이 null이 확실히 아닌경우 사용(null인경우 exception발생)
        Optional<Member> mm = Optional.of(member.get());
        System.out.println(mm.get().getName());
        //ofNullable은 null일수도 있을 때 사용(null 인경우 빈 optional객체를 반환)
        Optional<Member> mm2 = Optional.of(member.get());
        System.out.println(mm2.get().getName());
 
        //isPresent 대신 사용할 수 있는 방법
        // member가 널인경우 new member객체 생성 후 리턴
        Member resultMember = member.orElseGet(Member::new);
        // member의 값이 없으면 resultMember2에 null값을 채우고 리턴
        Member resultMember2 = member.orElse(null);
 
        //filter, flatMap, map 사용 예
        Optional<Member> member1 = member.filter(m -> m.getName().equals("홍길동")); // 홍길동이면 리턴
        //map의 경우 가공한 후 재가공이 필요없을 때 사용, flatMap의 경우 가공 후 재가공이 필요할 때 사용
        Optional<String> name1 = member.map(m -> m.getName() + "입니다"); // map
        Optional<String> name2 = member.flatMap(m -> Optional.of(m.getName())); // flatMap
    }
 
}
cs

Java 11버전에선 추가된 몇 메서드가 있는 것 같은데, 추후 11버전 이후를 사용하게 된다면 사용해봐야겠다.