Optional
Optional 객체 만들기
-
빈 Optional
Optional<Car> optCar = Optional.empty()
-
Optional.of
Optional에 null아닌 값만 포함하고자 할때는 Optional.of로 Optional객체를 만든다.Optional<Car> optCar = Optional.of(car)
-
Optional.ofNullable
null값을 저장할 수 있는 Optional을 만들때 사용한다.Optional<Car> optCar = Optional.ofNullable(car)
map와 flatMap을 이용한 Optional처리
Optional에 map와 flatMap을 이용하여 객체정보를 추출시 null-safe한 코드를 만들 수 있다.
//Optional로 데이터 모델 정의
public class Person {
private Optional<Car> car; //차가 null일수 있다는 것을 알 수 있음
public Optional<Car> getCar() { return car; }
}
public class Car {
private Optional<Insurance> insurance; //보험이 null일수 있다는 것을 알 수 있음
public Optional<Insurance> getInsurance() { return insurance; }
}
public class Insurance {
private String name; //보험에는 반드시 name이 있어야 한다는 것을 알 수 있다.
public String getName() { return name; }
}
//Optional을 이용해 자동차보험 이름 얻기
public String getCarInsuranceName(Optional<Person> person) {
return person.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unkown");
}
이전 글에 만들었던 함수 getCarInsuranceNameNullCheck과 비교해 보면 훨씬 가독성이 높으면서 null로 부터 안전한 코드가 만들어 졌다.
getCarInsuranceName 을 보면 Person에서 Car정보를, Car에서 Insurance 정보를 가지고 올때는 flatMap을 사용하고
Insurance의 name 정보를 가져 올때는 map을 사용하였다.
이유는 Person의 car 멤버 변수가 Optional.map(Person::getCar)
로 데이터를 추출할 경우 결과가 <Optional<Optional
디폴트 액션과 Option언랩unwrap
-
get()
get은 래핑된 값이 있으면 해당 값을 반환하고 값이 없으면 NoSuchElementException을 발생시킨다.
따라서 Optional의 값을 읽는 가장 간단한 메서드이지만 가장 안전하지 않은 메서드로 null이 있을 수 있는 Optional값을 읽을때는 사용하지 않는 것이 좋다. -
orElse
orElse 메서드를 이용하면 Optional이 값을 포함하지 않을 때 디폴트값을 제공할 수 있다..orElse("Unknown")
-
orElseGet(orElseGet(Supplier<? extends T> other))
Optional에 값이 없을 때만 Supplier을 실행하여 디폴트값을 생성한다. -
orElseThrow(Supplier<? extends X> exceptionSupplier)
Optional이 비어 있을때 예외를 발생시킬 예외의 종류를 선택 할 수 있다. -
ifPresent(Consumer<? super T> consumer)
값이 존재할 때 인수로 넘겨준 동작을 실행할 수 있다. 값이 없으면 아무일도 일어나지 않는다.