orElse ↔ orElseGet

김동훈·2023년 3월 25일
1

java에서 null처리는 하는 데에 Optional<>을 자주 쓰게 됩니다.
이 Optional<>의 메서드중 orElse와 orElseGet에 대해서 알아보았습니다.

orElse ↔ orElseGet의 차이점

우선 결론부터 말하자면 orElse는 null이던 아니던 파라미터으로 넘어온 메서드가 항상 호출되고, orElseGet은 null인 경우에만 호출됩니다. 이는 orElseGet가 supplier를 사용하기 때문에 벌어지는 것 입니다!

    public T orElse(T other) {
        return value != null ? value : other;
    }
    public T orElseGet(Supplier<? extends T> supplier) {
        return value != null ? value : supplier.get();
    }

orElse의 경우 value가 null인 경우 other자체를 리턴하고 있습니다.
하지만 orElseGet의 경우 supplier.get()를 리턴하고 있습니다.
supplier의 경우 함수형 인터페이스로 get()를 제공하고 있는데, 이는 lazy evaluation 특징이 있습니다. 실제로 .get()이 호출될 때 연산되는 것입니다. 따라서 두 메서드 모두 항상 실행되지만 orElseGet은 null인 경우에만 파라미터로 넘어온 메서드를 사용하게 됩니다.
그럼 한번 확인해보겠습니다.

name 테스트에서는 name이 donghun으로 null이 아니었기 때문에, orElse메서드에 의해 test()가 1번 호출되었음을 확인할 수 있습니다. name2 테스트에서는 name이 null이어서, orElse와 orElseGet 메서드에 의해 test()가 총 2번 호출됨을 알 수 있습니다.

orElse 와 orElseGet의 파라미터 호출 시점의 차이

위에서 orElseGet은 supplier를 사용하여 lazy하게 호출 된다는 특징이 있다고 했습니다.
그럼 이를 확인해보도록 합시다.
테스트를 위해 Optional클래스를 간단하게 구현한 custom<> 클래스를 사용하여 테스트 해보겠습니다.

위와 같이 custom<>클래스와 test 메서드를 작성해보았습니다. 그리고 orElse, orElseGet메서드의 정확한 파라미터 호출시점을 알기위해 currentTimeMillis()로 확인해보았습니다. 우리가 생각한대로 나온 것을 볼 수 있습니다. orElse의 경우 test()가 실행되고 난 후 그 반환값이 orElse메서드의 other이란 인자로 넘어가게 됩니다. 그래서 name2cutm → testcutm → customcutm 차례로 찍히는 것을 볼 수 있고, orElseGet의 경우 supplier.get()를 사용하므로 실제 사용시에 연산하게 됩니다. 따라서 test()가 먼저 실행되지 않고 .get()으로 직접 함수 호출할 때에 실행되어 name2cut → customcutm → testcutm 으로 각각 실행 순서가 다르다는 것을 확인했습니다.
profile
董訓은 영어로 mentor

0개의 댓글