Roel Notebook

[Java] Java Optional

by Roel Downey
728x90
반응형

자바 옵셔널은 자바 8부터 시작되었다. 공식 API 문서: 링크

 

왜 만들었을까? 

공식 API 문서를 들어가면 나와있다.

메서드가 반환할 결과값이 없음을 명백하게 표현할 필요가 있고, 널을 반환하면 에러를 유발할 가능성이 높은 상황에서 메서드의 반환 타입으로 옵셔널을 사용하자는것이다. 옵셔널 타입의 변수의 값은 절대 널 이어서는 안되며, 항상 옵셔널 인스턴스를 가리켜야 한다.

 

java.util.Optional<T> 클래스

Optional<T> 클래스는 Integer나 Double 클래스처럼 'T'타입의 객체를 포장해 주는 래퍼 클래스(Wrapper class)이다.

따라서 Optional 인스턴스는 모든 타입의 참조 변수를 저장할 수 있다.

 

이러한 Optional 객체를 사용하면 예상치 못한 NullPointerException 예외를 제공되는 메소드로 간단히 회피할 수 있다.

즉, 복잡한 조건문 없이도 널(null) 값으로 인해 발생하는 예외를 처리할 수 있게 된다.

 

Optional 객체 생성

Optional 객체를 생성하기 위해서는 Optional.of 와 Optional.ofNullable,  Optional.empty 3가지를 사용한다.

Optional을 필드로 사용하지 말자.

 

Optional<String> optString = Optional.of("Hello");

value가 null 인 경우 java.lang.NullPointerException 이 발생한다.

 

 

Optional<String> optString = Optional.ofNullable(null);

value가 null 인 경우 비어있는 Optional 반환한다.

 

 

Optional<String> emptyOpt = Optional.empty();

비어있는 Optional 객체를 생성한다.

 

 

Optional 처리

Optional 처리를 하기 위해 filter, map, flatMap 이 있다.

 

Optional.of("True").filter((val) -> "True".eqauls(val)).orElse("NO DATA"); // "True"

Optional.of("False").filter(
                              (val) -> "True".eqauls(val)
                            ).orElse("NO DATA"); // "NO DATA"

filter( ) 안에 값이 참이면 해당 필터를 통과 시키고 거짓이면 통과 시키지 않는다.

 

Integer intValue = Optional.of("1").map(Integer::valueOf).orElseThrow(NoSuchElementException::new); // string to integer

mapper 함수를 통해 입력값을 다른 값으로 변환하는 메서드 이다.

 

String result = Optional.of("result")
        .flatMap((val) -> Optional.of("good"))
        .get();
System.out.println(result); // print 'good'

mapper 함수를 통해 입력값을 다른 값으로 변환하는 메서드 이다.

 

map() 과 flatMap 다른점은 메서드 시그니처의 매개변수 이다. 

map() 은 제네릭으로 정의한다. flatMap 은 Optional 제네릭으로 정의한다.

flatMap() 메서드가 반환해야 하는 값은 Optional 이다.

 

Optional 마무리

ifPresent, isPresent, get, orElse, orElseGet, orElseThrow

 

// 예제 1 
Optional.of("test").ifPresent((value) -> {
	// something to do
});
// 예제2 (ifPresent 미수행)
Optional.ofNullable(null).ifPresent((value) -> {
	// nothing to do
});

최종적으로 연산을 끝낸 후 값이 비어있지 않다면 입력값으로 주어지고, 비어 있다면 메서드의 내용이 수행되지 않는다.

 

 

 

Optional.ofNullable("test").isPresent(); // true
Optional.ofNullable("test").filter((val) -> "result".eqauls(val)).isPresent(); // false

최종적으로 연산을 끝낸 후 객체가 존재하는지 여부를 판별

 

 

Optional.of("test").get(); // 'test'
Optional.ofNullable(null).get(); // NoSuchElementException!

객체를 꺼낸다. 비어있다면 예외가 발생한다.

 

 

String result = Optional.ofNullable(null).orElse("default");
System.out.println(result); // print 'default'

연산을 끝낸 후에 Optional로 객체가 비어있다면 기본값으로 제공할 객체를 지정한다.

Optional 객체가 비어있던 비어있지 않던 반드시 실행한다.

 

String result = Optional.ofNullable("input").filter("test"::equals).orElseGet(() -> "default");
System.out.println(result); // print 'default'

연산을 끝낸 후에 Optional로 객체가 비어있다면 기본값으로 제공할 함수를 지정한다.

Optional 객체가 비어있으면 실행한다. 새로운 객체 생성이나 새로운 연산을 수행하는 경우 사용한다.

 

 

Optional.ofNullable("input").filter("test"::equals).orElseThrow(NoSuchElementException::new);

연산 끝낸 후 Optional 객체가 비어있다면 예외 공급자 함수를 통해 예외를 발생시킨다.

 

 

 

 

 

 

 

 

 

 

728x90
반응형

블로그의 정보

What doing?

Roel Downey

활동하기