[JAVA] Optional

2024. 9. 8. 12:56Languages/JAVA

1. NullPointerException
 
작년에 JAVA를 접하고 학원에서 공부를 시작하고 지난주 회사에서 업무를 진행하면서, 엄청 많이 접했던 에러 중 하나가 NullPointerException이었다. 

 
그렇다면 NullPointerException 이 무엇일까? 참고했던 API 명세서에서는 NullPointerException 을 다음과 같이 설명하고 있다.
 
Thrown when an application attempts to use null in a case where an object is required. These include:

  • Calling the instance method of a null object.
  • Accessing or modifying the field of a null object.
  • Taking the length of null as if it were an array.
  • Accessing or modifying the slots of null as if it were an array.
  • Throwing null as if it were a Throwable value.

pointer는 변수의 메모리 공간 주소를 저장하는 변수(참조 변수) 로 생각하면 된다. 여기서, NullPointer는 Null을 참조한다고 생각을 하면 된다. 마치 아무것도 없는 곳을 참조하려고 하다보니, 에러가 발생하는 것이다. 즉, null 객체의 인스턴스에 접근하게 되면 발생하는 것이다.
 
2. Optional
 
그렇다면 NullPointerException을 해결할 수 있는 방법이 있을까? 참 감사하게도, Java에서는 null 을 다룰 수 있는 Optional 이란 클래스를 제공해준다. 여기서 Java 8 문서를 확인해보면, Optional이란..
 

A container object which may or may not contain a non-null value.   

 
이라고 설명하고 있는데, 모던 자바 인 액션에서는 다음과 같이 소개한다.
 

Optional이란 선택형 값을 캡슐화하는 클래스이다.
- 모던 자바 인 액션 p.369

 
예를 들어, Optional 클래스 중 ofNullable() 이라는 메서드가 있다. 해당 메서드를 이용하면 Optional이란 객체에 null이 쏙 담길 수 있다. 마치 과일 바구니처럼 사과라는 과일이 담겨 있을 수도 있고, 보이지 않는(?) 과일이 담겨 있는 것과 같다.
 
3. if(apple == null) or Optional.ofNullable(banana)
 
작년 학원 프로젝트할 때, NullPointerException을 만나면... 예외 처리를 하기 위해서  if(apple == null) 이란 조건문을 활용했다. 아니면 try-catch문을 이용해서 try {} catch (NullPointerException e) {} ... 등으로 활용했었다. 
 
그런데 이제는 Optional 이란 컨테이너 객체에 null을 담을 수 있다. Optional.ofNullable(apple).isPresent() 처럼 메서드를 이용하여 null일 경우, null이 아닐 경우를 생각해서 접근할 수도 있게 된다.
 
하단의 테이블은, API를 참고해서 적은 Optional 클래스의 메서드 중 일부이다. 

Method 설명 (API 문서 참고하세요~~)
empty() 비어있는 Optional 인스턴스를 반환
filter(Predicate<? super T> predicate) 주어진 predicate(generic 형식의 T를 받아 boolean을 반환)와 일치하면, 값을 가지고 있는 Optional 객체 반환, 그렇지 않으면 비어 있는 Optional 객체 반환
isPresent() 값이 주어지면 true, 주어지지 않으면 fales 반환
map(Function<? super T,? extends U> mapper) 값이 주어지면 제공했던 매핑함수(mapping function)을 반환
of(T value) 값이 있다면 값을 가지고 있는 Optional 반환
ofNullable(T value) 값이 있다면 값을 가지고 있는 Optional 반환, 없다면 비어 있는 Optional 반환
orElse(T other) 값이 있다면 값을 반환하고, 그렇지 않다면 other(여기에 적혀있는 내용)를 반환
get() 값이 있다면 값을 반환, 없다면 NoSuchElementException 반환

 
이 중 일부만을 이용해서 다음과 같은 코드를 작성할 수 있을 것 같다.

//예시 : Optional<Apple> apple = Optional.ofNullable(apple) 있다고 가정한다면
apple.flatMap(apple -> Optional.ofNullable(apple.getColor()))
    .filter(color -> color.equals("red"))                     
    .flatMap(color -> Optional.ofNullable(color.getDetail()))
    .orElse("상세내용없음");

 
4. 그렇다면 모든 객체를 Optional로?
 
Optional로 모든 객체를 감싸면 얼마나 좋을까... 그렇지만 모던 자바 인 액션 책에서 저자는 다음과 같이 설명한다.
 

모든 null 참조를 Optional로 대치하는 것은 바람직하지 않다.
Optional의 역할은 더 이해하기 쉬운 API를 설계하도록 돕는 것이다.
즉, 메서드의 시그니처만 보고도 선택형값인지 여부를 구별할 수 있다.
- 모던 자바 인 액션 p.370
 

그렇다. Optional의 목적을 기억해두자!
 

References
1. JAVA API : https://docs.oracle.com/javase/8/docs/api/
2. Modern Java in Action (모던 자바 인 액션), 11장 null 대신 Optional 클래스, p.363 ~ p.388, 한빛미디어
 
 

'Languages > JAVA' 카테고리의 다른 글

[JAVA] Time  (1) 2025.02.20
[JAVA] Stream++  (1) 2024.10.05
[JAVA] max()  (0) 2024.04.04
[JAVA] 간단한 Predicate<T>  (0) 2024.03.31
[JAVA] Stream  (0) 2024.01.24