참고
https://www.oracle.com/technical-resources/articles/java/java8-optional.html
https://www.baeldung.com/java-difference-map-and-flatmap
NullPointerException !?
개발을 하면서 많이 경험했던 Exception은 아마 NullPointerException 이 아닐까 싶다.
위와 같은 모델 구조가 있다고 가정했을 때,
차에 포함된 네비게이션의 버전을 알고 싶다.
String version = computer.getNavigation().getVersion();
Car에서 Navigation은 옵션 중 하나이다.
만약 Navigation이 없는 차라면 해당 코드 호출 시 NullPointerException 이 발생하게 된다. (null.getVersion())
그러면 어떻게 해야 에러가 발생하는 것을 막을 수 있을까?
아래와 같이 방어 코드를 구현할 수 있다. 하지만 nested 체크로 인해 가독성이 떨어지고
Null 체크를 위해 수많은 보일러 플레이트 코드를 구현해야 한다.
String version = "UNKNOWN";
if(car != null){
Navigation navigation = car.getNavigation();
if(navigation != null){
version = navigation.getVersion();
}
}
JAVA 8 Optional
Java8에서 이러한 Null Exception 문제를 효과적으로 다룰 수 있는시켜 줄 java.util.Optional 클래스를 도입하였다.
Optional은 간단히 말해서 옵셔널한 Value를 포함하는 클래스이다.
Value가 포함되어 있을 수도 있고, 없을 수도 있다.
Navigation 버전을 알고 싶을 때, Optional의 메소드를 통해 아래와 같이 구현할 수 있다.
public class Car {
private Optional<Navigation> navigation;
public Optional<Navigation> getNavigation() { ... }
...
}
public class Navigation{
public String getVersion(){ ... }
}
String name = car.flatMap(Car::getNavigation)
.map(Navigation::getVersion)
.orElse("UNKNOWN");
Optional 객체 생성
empty 객체 생성
Optional<Soundcard> sc = Optional.empty();
non-null value 객체 생성
Navigation navigation = new Navigation();
Optional<Navigation> navi = Optional.of(navigation);
Optional.of로 null 이 전달될 경우 nullpointerException이 발생한다.
Navigation navigation = null;
Optional<Navigation> navi = Optional.of(navigation);
Value 객체가 Null 일 가능성이 있다면 ofNullable을 사용한다.
Optional<Navigation> navi = Optional.ofNullable(navigation);
Value가 존재한다면?
ifPresent()
navigation 이 존재한다면 출력
AS-IS
if(navigation != null){
System.out.print(navigation);
}
TO-BE
Optional<Navigation> navi = Optional.ofNullable(navigation);
navi.ifPresent(System.out::print);
isPresent()로 Value가 존재하는지 여부를 체크할 수 있다.
get() 은 Optional에 포함된 value를 리턴한다.
if(navigation.isPresent()){
System.out.print(navigation.get());
}
Optional로 Default Value처리
Navigation navigation = (maybeNavi != null)? maybeNavi : new Navigation("default");
TO-BE
Optional클래스의 orElse로 Value가 Null 일 경우 Default 값 리턴
Optional<Navigation> maybeNavi = Optional.ofNullable(navigation);
Navigation navigation = maybeNavi.orElse(new Navigation("default"));
orElseThrows()로 Null일 경우 Exception 을 던지는 것도 지원
Filter Method 사용 시 특정 Value Rejecting
AS-IS
Navigation navi = ...;
if(navi != null && "3.0".equals(navi.getVersion())){
System.out.println("ok");
}
TO-BE
Optional<Navigation> maybeNavi = ...;
maybeNavi.filter(navi -> "3.0".equals(navi.getVersion())
.ifPresent(() -> System.out.println("ok"));
Map Method로 Value 추출하기
Optional<Navigation> maybeNavigation = maybeCar.map(Navigation::getNavigation);
maybeCar.map(Navigation::getNavigation)
.filter(navi -> "3.0".equals(navi.getVersion())
.ifPresent(() -> System.out.println("ok"));
'💻IT > Java' 카테고리의 다른 글
[Java] Java 8 Method Reference (메소드 참조) (0) | 2021.12.12 |
---|---|
[Java] Java 8 Functional Interface (0) | 2021.12.10 |
[Java] Java 8 Stream API (0) | 2021.12.03 |
[Java] Deque 자료 구조 (LinkedList 메소드) (0) | 2021.11.15 |
[Java] Convert Array to List / Convert List to Array (0) | 2021.10.18 |