최근 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 |
---|