1) Optional이란?
- Optional은 래퍼 클래스입니다
래퍼 클래스란 T타입의 참조 변수를 갖는 클래스입니다.
래퍼 클래스의 대표적인 예시로는 Integer나 Long타입이 있습니다.
public final class Optional<T>{
private final T value;
}
- Optional은 제네릭 T타입을 갖고 있기 때문에 어떤 타입이던지 저장할 수 있습니다. 그리고 클래스 안에 T타입의 참조 변수를 갖고 있습니다.
- 여기서 T에는 모든 종류의 객체 혹은 null을 저장할 수 있습니다.
2) Optional이 필요한 이유
(1) null을 직접 다루는 것은 NullPointerException(이하 NPE)이 발생할 수 있으므로 위험합니다.
-> 그래서 객체안에 담아서 간접적으로 다루면 NPE의 위험을 피할 수 있습니다.
(2) null을 직접 다루면 null체크를 해야하므로 코드가 지저분해집니다.
(1),(2)와 같은 문제를 해결하려고 간접적으로 null을 다룹니다.
- 다음과 같은 코드가 있다고 할 때,
반환값은 null이거나 아니면 객체입니다.
Object result = getResult();
- 그런데 아래와 같은 코드를 실행하면,
result가 null일때 NPE가 발생합니다.
result.toString();
- 그래서 항상 if문을 적어줘야 합니다.
if(result != null){
result.toString();
}
- 이런 문제점들을 해결하기 위해 나온 것이 Optional입니다.
- 지금까지는 객체에 null을 담았다면, 이제는 null을 Optional 객체에 넣습니다.
Optional 객체는 존재하므로 주소가 있습니다. 단, Optional 객체의 value 값이 null인 것입니다.
- 그래서 null값을 직접 다루는 것이 아니라 Optional 객체 안에 넣습니다.
그러면 결과가 null이더라도 result의 값은 null이 아닙니다.
어떤 객체의 주소가 있으니까 항상 null이 아닙니다.
- 따라서 NPE가 발생하지 않고, null체크가 필요 없습니다. 그래서 코드도 간결해집니다.
-> 즉, null을 간접적으로 다루려고 하는 것이 Optional 입니다.
2) Optional<T> 객체 생성하기
- Optional<T> 객체는 Optional 클래스의 static 메서드인 of 메서드를 쓰면 됩니다.
String str = "abc";
Optional<String> optVal = Optional.of(str);
Optional<String> optVal = Optional.of("abc");
Optional<String> optVal = Optional.of(null); // NullPointerException 발생
Optional<String> optVal = Optional.ofNullable(null); // OK
- 이를 도식으로 나타내면 다음과 같습니다.
str 0x60 -> "abc"
optVal 0x20 -> str 0x60 -> "abc"
- 이 때, str은 null 일 수 있지만, optVal은 절대 null이 아닙니다.
- Optional에 null을 그냥 넣는 것은 안되고, NPE가 발생합니다.
그래서 null을 넣는 옵션으로는 ofNullable 메소드를 만들어야 합니다.
- Optional 객체는 T타입의 제네릭 참조 변수를 저장하기 때문에,
모든 타입의 객체를 저장할 수 있습니다.
-> 이제는 null이 될 수 있는 값은 Optional<T>를 만들어서 그 안에 넣습니다.
- null 객체를 초기화할 때도 다음과 같이 하는 편이 좋습니다.
Optional<String> optVal = null; // X
Optional<String> optVal = Optional.empty(); // O
3) Optional<T> 객체의 값 가져오기
(1) Optional 객체의 값 가져오기
- Optional 객체의 값을 가져오는 방법에는 get(), orElse(), orElseGet(), orElseThrow()가 있습니다.
Optional<String> optVal = Optional.of("abc");
String str1 = optVal.get(); // optVal에 저장된 값을 반환. null이면 예외 발생
String str2 = optVal.orElse(""); // optVal에 저장된 값이 null일 때는, ""를 반환
String str3 = optVal.orElseGet(String::new); // 람다식 사용 가능 () -> new String(), 메서드 참조가 람다식으로 변경됩니다.
(=> T orElseGet(Supplier<? extends T> other))
STring str4 = optVal.orElseThrow(NullPointerException::new); // 널이면 예외 발생. 예외 종류 지정 가능
(=> T orElseThrow(Supplier<? extends X> exceptionSupplier))
(2) isPresent()
- Optional 객체의 값이 null이면 false, 아니면 true를 반환합니다.
if(Optional.ofNullable(str).isPresent()){
System.out.println(str);
}
(3) Optional get(), orElse(), orElseGet(), orElseThrow() 사용하기
class Ex14_0{
public static void main(String[] args){
// Optional<String> opt = null; // OK. 하지만 바람직하지는 않음
Optional<String> opt = Optional.empty();
System.out.println("opt=" + opt);
String str = "";
// try{
// str = opt.get();
// }catch(Exception e){
// str = ""; // 예외가 발생하면 빈문자열("")로 초기화
// }
// str = opt.orElse(""); // Optional에 저장된 값이 null이면 "" 반환
// str = opt.orElseGet(() -> "EMPTY"); // Optional에 저장된 값이 null이면 "" 반환
// str = opt.orElseGet(() -> new String()); // Optional에 저장된 값이 null이면 "" 반환
str = opt.orElseGet(String::new); // Optional에 저장된 값이 null이면 "" 반환
System.out.println("str=" + str);
}
}
// 실행 결과
opt = Optional.empty
str =
참고
남궁성 자바의 정석
'Java' 카테고리의 다른 글
Optional 소개 (더 자바, Java 8 강의) (0) | 2022.09.12 |
---|---|
추상 클래스, 추상 메서드 (0) | 2022.09.04 |
예외 선언(Exception Handling) - 메서드에 예외 선언하기, finally 블럭 (0) | 2022.09.01 |
예외 처리(Exception Handling)(4) - 예외 발생시키기 (0) | 2022.08.30 |
예외 처리(Exception Handling)(3) - printStackTrace(), 멀티 catch 블럭 (0) | 2022.08.30 |