반응형
Optional 은 null 값을 잘 처리하기 위한 클래스입니다.
without Optional
public class SimpleNpeExampleMain {
public static void main(String[] args) {
String string = getNullString();
System.out.println("string=" + string);
System.out.println(string.toUpperCase());
}
private static String getNullString() {
return null;
}
}
근데 이렇게 당연하게 null 이 터지는 경우는 실제 상황에서 없을 것이다.
좀 더 현실적인 경우를 생각해보자.
public class MapRepository {
private Map<String, String> map = new HashMap<>();
MapRepository() {
map.put("EXIST_KEY", "value");
}
public String getValue(String key) {
return map.get(key);
}
}
public class WithoutOptionalExampleMain {
public static void main(String[] args) {
MapRepository mapRepository = new MapRepository();
String string = mapRepository.getValue("NOT_EXIST_KEY");
System.out.println("string=" + string);
System.out.println(string.toUpperCase());
// NullPointerException을 피하려면 이렇게 Null 체크를 해야함.
// if(string != null)
// System.out.println(string.toUpperCase());
}
}
mapRepository 에 없는 key를 넣어서 getValue() 를 했으니 string 은 null 이 될 것이다.
다라서 string.toUpperCase() 에서 npe 가 발생한다.
with Optional
Optional 을 왜 사용할까?
Object obj = stream.getFirst();
if(obj == null)
new MyFancyException();
-> Optional 을 사용하지 않았을 때
stream.getFirst().orElseThrow(() -> new MyFancyException())
-> Optional 을 사용했을 때 : 좀 더 fancy 한 코드가 완성된다.
이제 Optional 을 잘 사용해보기 위해서,
사용하는 3가지 예제를 보자.
예제
public class WithOptionalExampleMain {
public static void main(String[] args) {
MapRepository mapRepository = new MapRepository();
Optional<String> string = mapRepository.getOptionalValue("NOT_EXIST_KEY");
// Optional<String> string = mapRepository.getOptionalValue("EXIST_KEY");
string.ifPresentOrElse(
str -> System.out.println(str.toUpperCase()), // Optional이 Empty가 아닐 때 실행
() -> {
throw new RuntimeException("키가 존재하지 않습니다."); // Optional이 Empty일 때 실행
}
);
}
}
예제
public class WithOptionalExampleMain2 {
public static void main(String[] args) {
// 이전 코드보다 간결한 코드
MapRepository mapRepository = new MapRepository();
String string = mapRepository.getOptionalValue("NOT_EXIST_KEY").orElseThrow(
() -> {throw new RuntimeException("키가 존재하지 않습니다.");}
);
System.out.println(string.toUpperCase());
}
}
예제
public class WithOptionalExampleMain3 {
public static void main(String[] args) {
// Optional의 정적 팩토리 메서드 사용
MapRepository mapRepository = new MapRepository();
String string = Optional.ofNullable(mapRepository.getValue("NOT_EXIST_KEY"))
.orElseThrow(RuntimeException::new);
System.out.println(string.toUpperCase());
}
}
- 내가 쓰는 라이브러리의 메서드 반환 타입이 Optional 인 경우
- 그대로 orElseThrow 같은 메서드로 사용
- 내가 쓰는 라이브러리의 메서드 반환 타입이 Optional 이 아닌 경우
- Optional.ofNullable 로 Optional 객체 생성 후, orElseThrow 같은 메서드로 사용
public class ListOptionalExampleMain {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
Integer filteredInteger = list.stream()
.filter(value -> value.equals(100))
.findFirst()
.orElseThrow(() -> {
throw new RuntimeException("100에 해당하는 요소가 없습니다.");
});
System.out.println(filteredInteger);
}
}
-> stream Api 와 연계해서 사용하면 굉장히 잘 어울린다.
stream 을 사용하면서 있을 수도 있고 없을 수도 있는 상황에, Optional 을 사용할 수 있기 때문이다.
반응형
'백엔드 데브코스' 카테고리의 다른 글
[Java] getter, setter, 생성자로 알아보는 객체지향적인 코드 (0) | 2023.09.25 |
---|---|
[Java] if문 제거하기 - 리팩토링 (0) | 2023.09.25 |
[Java] Object 클래스와 주요 메서드 - equals(), hashCode(), toString() (0) | 2023.09.22 |
[Java] Checked & Unchecked exception 의 차이 (0) | 2023.09.22 |
[Java] Enum 이란 (0) | 2023.09.22 |