Java

Optional 클래스

최근 Java spring을 배우면서, Optional이란 클래스를 자주 접했다. Null 값을 처리하기 위해서 사용하는 클래스라는 설명은 들었지만, 정확히 어떤 기능을 하는 지 알면 좋을 것 같아 블로그 글로 정리하기로 했다.

 

Optional

Optional 클래스는 자바 8부터 도입된 클래스이다. 이 클래스의 목적은 객체 호출 도중 발생하는 null 값을 보다 간단히 처리하기 위해서인데, 기존에는 객체가 null값인지 확인하기 위해 아래와 같은 if문을 사용해야 했다.

 

import java.util.*;
import java.lang.*;
import java.io.*;

class Apple{
  public String eat(){
   	return "냠냠";
  }
}

class Test{
  public static void main(String[] args){
    Apple apple = getApple();
    String str;
    if(apple==null){
        str = "사과가 존재하지 않습니다.";
    }
    else str = apple.eat();
    System.out.println(str);
  }
  
  public static Apple getApple(){
    return new Apple();
  }
}

하지만 Optional 클래스를 사용하면 아래와 같이 코드를 간결하게 바꿀 수 있다.

import java.util.*;
import java.lang.*;
import java.io.*;

class Apple{
  public String eat(){
   	return "냠냠";
  }
}

class Test{
  public static void main(String[] args){
    Optional<Apple> opt = Optional.of(new Apple());
    String str = opt.map(Apple::eat)
                    .orElse("사과가 없어요!");
    System.out.println(str);
  }
  
  public static Apple getApple(){
    return new Apple();
  }
}

이처럼 Optional 클래스는 필요한 곳에 사용하면 코드의 복잡도를 줄일 수 있다. 그러면 Optional의 메소드를 알아보자.

 

1. of(T value), ofNullable(T value), empty()

  - 이 메소드들은 Optional 객체를 생성하는 메소드이다. of(T value)는 value가 null일 때 NullPointerException을 발생시키며, ofNullable(T value)는 value가 null이라면 빈 Optional 객체를 생성해준다. empty()는 빈 Optional 객체를 생성해준다. 여기서 빈 Optional 객체란, 내부에 다른 객체를 가지고 있지 않은 Optional 객체를 말한다.

 

    Optional<Apple> apple1 = Optional.of(new Apple()); 
        
    //Optional<Apple> apple2 = Optional.of(null); //NPE 발생
        
    Optional<Apple> apple3 = Optional.ofNullable(new Apple());
        
    Optional<Apple> apple4 = Optional.ofNullable(null); // 빈 Optional 객체 생성
        
    Optional<Apple> apple5 = Optional.empty();

 

2. get()

  - Optional 객체 내부에 있는 객체를 리턴한다.

 

        String fruit = Optional.of("orange").get();
        System.out.println(fruit); // orange

 

3. orElse(T other)

  - Optional 내부에 객체가 있을 경우 그 객체를 리턴하고, 아니면 other를 리턴한다.

 

4. orElseGet(Supplier<? extends T> other)
  - orElse와 유사하게 Optional 내부에 객체가 있을 경우 그 객체를 리턴하고, 아니면 other를 리턴한다. orElse와의 차이 점은 other가 함수형태라는 점이다.

 

5. orElseThrow(Supplier<? extends X> exceptionSupplier)

  - Optional 내부에 객체가 있으면 그 객체를 리턴하고, 아니면 exceptionSupplier에 지정된 예외를 발생시킨다. 

 

Optional.of("red").filter(val->val.equals("blue"))
  .orElseThrow(()->new Exception("Optional 객체가 비어있어요!"));
  //filter 함수에 의해 Optional 객체가 비게 되어 예외가 발생한다.

6. filter(Predicate<? super T> predicate)

  - predicate 결과 값이 true이면 Optional 객체를 그대로 리턴하고, 아니면 빈 Optional 객체를 리턴한다.

 

        String t1 = Optional.of("red").filter(color->color.equals("red")).orElse("different"); 
        System.out.println(t1); //red
        
        String t2 = Optional.of("red").filter(color->color.equals("blue")).orElse("different"); 
        System.out.println(t2); //different

 

7. map(Function<? super T, ? extends U> mapper)

  - Optional 객체가 비어있지 않다면 내부 객체에 map 내부의 함수를 적용시키고, 그 결과를 담은 Optional 객체를 리턴한다.

 

        Optional<Integer> t3 = Optional.of("snake").map(str -> str.length());
        System.out.println(t3.get()); // 5
        
        Optional<Integer> t4 = Optional.of("elephant").map(str -> str.length());
        System.out.println(t4.get()); // 8
        
        /*Optional t5 = Optional.empty().map(str -> str.length());
        System.out.println(t5.get());*/ // error

 

8. ifPresent(Consumer<? super T> consumer)

  - Optional 객체가 비어있지 않다면 내부 객체에 대해 ifPresent 내부의 식을 적용한다. 비어있다면 아무것도 하지 않는 다.

 

Optional.of("spider").ifPresent(System.out::println); // spider 출력

Optional.of("giant").ifPresent(val ->System.out.println(val.toUpperCase())); // GIANT 출력

 

9. isPresent()

  - Optional 객체가 비어있다면 false, 아니라면 true를 리턴한다.

 

지금까지 Optional 객체와, 같이 사용하면 좋을 다양한 메소드들에 대해 알아보았다. Optional 객체를 필요한 곳에 사용하면 코드 복잡도를 크게 줄일 수 있을 것으로 보인다.

 

'Java' 카테고리의 다른 글

Garbage Collection  (0) 2021.01.18