du.study기록공간

Java Optional 사용하기 본문

자바

Java Optional 사용하기

du.study 2020. 5. 17. 21:17
728x90

이번에는 Optional 사용법에 대해 기록해보려 합니다.

 

먼저 Optional은 NULL 처리( 또는 반환값이 없는 ) 에 유용하게 사용되며 이 덕분에 런타임에서 발생되는 NullPointerException를 좀 더 깔끔하도록?(사실 코드 보는사람 케바케인지라.. 만약 자바 개발자가 Optional을 모른다면) 지원해주고 있습니다.

 

현재 저희 프로젝트에서도 dao 에서 받아온 값을 Optional을 통해 처리하고 있어 이번 기회에 기록해보려 합니다.

 

테스트는 간단하게 main함수에서 private함수를 호출하는 식으로 테스트 할 예정입니다.

 

먼저 Optional을 살펴보면 다음과같은 변수를 가지고 있습니다.

public final class Optional<T> {
    private static final Optional<?> EMPTY = new Optional();
    private final T value;
    ....
        
}

T value 를 통하여 우리가 생성 또는 가공한 객체가 저장되게되며, EMPTY는 Optional.emtpy()에서 사용되게 됩니다.

 

 

본격적으로 Optional사용을 함수 리턴값으로 Optional을 선언하면 다음과 같이 보이는 3개가 있습니다.

 

1. of

public static <T> Optional<T> of(T value) {
    return new Optional(value);
}

private Optional(T value) {
    this.value = Objects.requireNonNull(value);
}

public static <T> T requireNonNull(T obj) {
    if (obj == null) {
        throw new NullPointerException();
    } else {
        return obj;
    }
}

내부적으로 해당 value를 저장하게 되며, 넘겨준 value가 null일 시, NullPointerException()을 뱉어줍니다.

 

2. empty()

private Optional() {
    this.value = null;
}

public static <T> Optional<T> empty() {
    Optional<T> t = EMPTY;
    return t;
}

empty의 경우, value가 null이 들어간 객체를 생성하게 됩니다. EMPTY의 경우 위에서 보면 new Optional(); 를 통한 생성을 한것을 볼 수 있습니다.

 

 

3. ofNullable

public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}

해당부분은 of 와 empty()가 합쳐진 구문으로 특징은 value가 null 경우에 empty로 리턴이 되게됩니다.

 

null인경우 바로 에러를 뱉는 경우도 있으나, 보통 throw new NullPointerException(); 를 직접 선언하는 경우는 거의 없을거라고 생각이 듭니다.( 각 프로젝트별 에러 커스텀을 던지지 않을까..) 

확인하고 싶은부분은 해당 value가 null인지에 대한 유무로 필자는 우선 ofNullable을 통해서 Optional객체를 받고 추가 처리를 하고 있습니다.

 

간단한 예시 코드입니다.

private static Optional<String> optionalNullTest(){
    return Optional.ofNullable(null);
}

private static Optional<String> optionalValueTest(){
    return Optional.ofNullable("hello world");
}
-------------------------------------------------------

한개는 null을 뱉어내는 코드, 한개는 hello world 라는 String 을 뱉어내는 메서드입니다.

 

해당 메서드들을 호출했을때, 어떻게 처리하는지에 대한 예시를 살펴보겠습니다.

 

1. orElse 

public T orElse(T other) {
    return this.value != null ? this.value : other;
}

------------------------------------------------------------------
String test1 = DemoApplication.optionalNullTest().orElse("test");
System.out.println(test1); // test

test1 = DemoApplication.optionalValueTest().orElse("test");
System.out.println(test1); // hello world

orElse의 경우, 만약 value가 null이게 되면 T order로 받은 객체를 리턴하게 됩니다. ( 여기선 test라는 String)

 

 

2. orElseGet

public T orElseGet(Supplier<? extends T> supplier) {
    return this.value != null ? this.value : supplier.get();
}
-------------------------------------------------------------------------
String test1 = DemoApplication.optionalNullTest().orElseGet(() -> "test");
System.out.println(test1); // test

test1 = DemoApplication.optionalValueTest().orElseGet(() -> "test");
System.out.println(test1); // hello world

orElseGet의 경우, 내부적으로 supplier 을 가지고 있으며, 다음과 같이 Supplier지원식으로 선언하여 넘겨주면 리턴값으로 넘어오게 됩니다.

 

3. orElseThrow

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (this.value != null) {
        return this.value;
    } else {
        throw (Throwable)exceptionSupplier.get();
    }
}
--------------------------------------------------------------------------------------------------
String test1 = DemoApplication.optionalNullTest().orElseThrow(() -> new NoSuchElementException());
System.out.println(test1); // Exception in thread "main" java.util.NoSuchElementException

orElseThrow 의 경우 value가 null인경우 에러를 던지게 됩니다. 보통 NullPointerException가 던져질 것이나, 다음과같이 다른 에러를 던질 수 있고, 각 서비스에서 커스텀한 에러를 뱉을 수 있습니다.

 

 

4. isPresent

public boolean isPresent() {
    return this.value != null;
}
-----------------------------------------------------------------------
Optional<String> optionalTest =  DemoApplication.optionalValueTest();
if(optionalTest.isPresent()){
    String test = optionalTest.get();
    System.out.println(test); // hello world
}

isPresent의 경우 boolean 값으로 value가 null인지 아닌지 확인하게 됩니다. 즉 값이 있으면, get()을 통해서 변수를 받아와 처리하는 로직을 태우게 됩니다.

 

단 해당 방식은 직접 Optional로 받아서 다시 체크하는 식으로, 조금 코드가 길어지게 됩니다.

 

간단하게 Optional에 대해서 사용하고 있는 구문을 작성해보았습니다.

Optional사용 예제를 확인하면서, 서비스 코드에서도 참 여러방식으로 사용되는것을 확인해서..  좀 통일해야겠다는 생각이 드네요

728x90

'자바' 카테고리의 다른 글

Spring boot +gradle+node build with kotlin  (0) 2020.10.25
Java Async - CompletableFuture  (0) 2020.05.25
Java stream sort multiple fields  (0) 2020.04.25
Java Map java.util.concurrent.ConcurrentHashMap  (0) 2020.04.06
java.util.Set(1) HashSet  (0) 2020.03.28
Comments