상세 컨텐츠

본문 제목

Java Optional

개인 공부/Spring-boot,Java

by 카페코더 2020. 7. 1. 18:10

본문

반응형

도입 이유

Java Optional이 도입되기 전, 많은 개발자들은 null로 인해 편리함 보단 불편함을 많이 받았다.

우편물 송장을 예시로 살펴보자. 우편물을 보낼 때, 우리는 수령인의 기본 정보가 적힌 송장을 붙여 발송한다. 모든 정보가 다 올바르게 적혀있는 경우엔, 문제 없이 우편물은 수령인에게 정확하게 도착하지만, 받는 사람의 이름이 적혀있지 않다면, 우편물이 올바르게 도착한다는 보장이 없다. 

프로그래밍도 마찬가지다. 필요한 내용이 null이라면, 우리는 출력할 때 nullPointException이 발생할것이다. 이것의 예외처리를 위해 우리는 try-catch 문법 혹은 if-else 문법을 통해 처리하곤 한다. 하지만 이 방법도 적은양을 검사할 때는 문제가 없겠지만, 1억개를 검사해야 한다 생각해보면 노가다도 이런 노가다가 없을것이다.

이런 불편함을 해소하기 위해, Java8부터는 함수형 언어에서 그 해법을 찾아 Optional이라는 개념이 등장한다.


Optional (Optional<T>)

Optional은 null이 될 가능성이 있는 객체를 감싸고있는 Wrapper Class다. Stream이나, Collection과 비슷하지만, 원소가 0개 ~ 1개 까지 가질 수 있는 차이점이 있다. 프로그래밍을 하다보면 null로 인해 프로그램이 죽는 경우가 많은데, 이것을 처리할 수 있는 특수한 자료형이라 생각하면 쉽다.

Optional을 사용하며 기대할 수 있는 효과는 다음과 같다.

  1. NullPointException를 직접 처리할 필요가 없어진다.
  2. 해당 변수가 null일 수 있다는 가능성을 열어둬, 불필요한 예외처리 로직을 줄일 수 있다.

Optional 객체의 생성

기본적으로 Optional 객체의 생성은 of() 또는 ofNullable() 메소드를 사용하여 생성할 수 있다.

// Optional<T> tOptional = Optional.ofNullable(Tobject);

Optional<String> stringOptional = Optional.ofNullable("cafeCoder");
Optional<String> stringOptional = Optional.of("cafeCoder");
  •  of() 메소드 

    null이 아닌 명시된 값을 갖는 Optional 객체를 반환한다.
    만약 인자가 명시되지 않고, null인 상태로 주입된다면, NullPointerException이 발생하게 된다.

  • ofNullable() 메소드

    null이 될 가능성이 있는 값을 갖는 Optional 객체를 반환한다.
    인자가 명시되지 않고, null인 상태로 주입되어도 NullPointerException이 발생하지 않는다.

즉, null이 들어올 일이 없다 => of()
null이 들어올 가능성이 있다 => ofNullable() 

을 사용하면 된다.


Optional 객체의 사용

Optional 객체를 단순히 get() 메소드를 통해 사용한다면, NoSuchElementException이 발생한다. 저장된 값이 null일 가능성이 없는 경우에는 get()메소드를 사용해도 괜찮다.

그렇다면 저장된 값이 null일 가능성이 있는 경우에는 어떻게 사용하는지 알아보자.

1. isPresent() 메소드를 통해 확인 후 사용하기

import java.util.Optional;

public class main {
    public static void main(String[] args) {
        Optional<String> stringOptional = Optional.ofNullable(null);

        if(stringOptional.isPresent()) {
            System.out.println(stringOptional.get());
        }
        else {
            System.out.println("Optional 객체가 비워져 있습니다.");
        }
    }
}
실행 결과

Optional 객체가 비워져 있습니다.

 

2. orElse() 메소드를 통해 사용하기

import java.util.Optional;

public class main {
    public static void main(String[] args) {
        Optional<String> stringOptional = Optional.ofNullable(null);
        System.out.println(stringOptional.orElse("Optional 객체가 비워져 있습니다."));

        stringOptional = Optional.ofNullable("cafeCoder");
        System.out.println(stringOptional.orElse("Optional 객체가 비워져 있습니다."));
    }
}
실행 결과

Optional 객체가 비워져 있습니다.
cafeCoder

첫 Optional객체의 경우 저장된 값이 null이므로, orElse() 메소드에 전달한 인자가 출력되었고, 다음 Optional 객체의 경우, "cafeCoder"로 인자가 전달되어 cafeCoder가 출력된 것을 볼 수 있다.

즉, 저장된 값이 null이라면, orElse() 메소드 내 인자가 출력되고, 아니라면 저장한 값이 출력된다.

 

3. orElseGet() 메소드를 통해 사용하기

import java.util.Optional;

public class main {
    public static void main(String[] args) {
        Optional<String> stringOptional = Optional.ofNullable(null);
        System.out.println(stringOptional.orElseGet(String::new));
    }
}

 

실행 결과

 실행 결과가 비워져있는것을 볼 수 있다. orElseGet() 메소드는 값이 존재한다면 그 값을 출력하고, 비워져 있다면 인수로 전달된 람다 표현식의 결과값을 반환한다.

 

4. orElseThrow 메소드를 통해 사용하기

import java.util.Optional;

public class main {
    public static void main(String[] args) {
        Optional<String> stringOptional = Optional.ofNullable("cafeCoder");
        System.out.println(stringOptional.orElseThrow(RuntimeException::new));

        stringOptional = Optional.ofNullable(null);
        System.out.println(stringOptional.orElseThrow(RuntimeException::new));
    }
}
실행 결과

cafeCoder
Exception in thread "main" java.lang.RuntimeException
	at java.util.Optional.orElseThrow(Optional.java:290)
	at main.main(main.java:9)

첫 Optional은 null이 아닌, "cafeCoder"를 인자로 받아 orElseThrow() 메소드를 통해 출력하였을 때, cafeCoder가 출력된 것을 볼 수 있다.

두 번째 Optional은 null을 인자로 받아 orElseThrow() 메소드를 통해 출력하였을 때, 예외가 발생한 것을 볼 수 있다.

즉, orElseThrow() 메소드는 저장된 값이 존재하면 저장된 값을 출력하고, 아닌 경우 인자로 전달 된 예외를 발생시키는 것을 알 수 있다.

반응형

관련글 더보기

GitHub 댓글

댓글 영역