보수적인 자세
null 때문에 발생하는 문제
다른 언어에서 null 대신 무얼 사용하나?
값이 있으면 Optional 클래스는 값을 감싸고 없으면 Optional.empty 메서드로 Optional을 반환
Optional.empty()는 Optional 객체이므로 이를 참조해도 익셉션이 발생하지 않는다
public class Car{
private Optional<Insurance> insurance;
public Optional<Insurance> getInsurance(){
return insurance;
}
}
public class Insurance {
private String name;
public String getName() {
return name;
}
}
위 예시처럼 보험회사는 반드시 이름을 가져야 하기 때문에 String으로, 차는 보험을 갖고 있을 수 도 없을 수 도 있기 때문에 Optional로 표현하면 모델의 의미semantic이 더 명확해졌다
Optional<Car> optCar = Optional.empty();
Optional<Car> optCar = Optional.of(car);
Optional<Car> optCar = Optional.ofNullable(car);
get메서드로 Optional의 값을 가져올 수 있는데 이때 비어있으면 예외가 발생
Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);
스트림의 map은 스트림의 각 요소에 제공된 함수를 적용하는 연산
Optional이 비어있으면 아무 일도 일어나지 않는다
스트림의 flatMap은 함수를 인수로 받아서 다른 스트림을 반환하는 메서드
함수를 적용해서 생성된 모든 스트림이 하나의 스트림으로 병합되어 평준화
public String getCarInsuranceName(Optional<Person> person) {
return person.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unknown");
}
public Set<String> getCarInsuranceNames(List<Person> people) {
return people.stream()
.map(People::getCar)
.map(optCar -> optCar.flatMap(Car::getInsurance))
.map(optIns -> optIns.map(Insurance::getName))
.flatMap(Optional::stream)
.collect(toSet());}
Optional객체를 가져올때 null값일 수 있기 때문에 map 변환을 수행
두 Optional 객체를 함께 사용하는 것도 가능
optInsurance.filter(insurance -> "CambridgeInsurance".equals(insurance.getName())
.ifPresent(x -> System.out.println("ok");
필터로 특정값이 있다면 그 값을 반환하고 없다면 Optional 객체를 반환한다
Optional<Object>value = Optional.ofNullable(map.get("key"));
Map에서 단순 get 했을때 해당 값이 없으면 null을 반환하는데 Optional로 감싸서 Optional을 반환하게 바꿀 수 있다
public Optional<Integer> stringtoInt(String s) {
try{
return Optional.of(Integer.parseInt(s));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
위 예시에서 s가 null일 경우 동작하지 않지만 Optional을 사용해 null일때도 원하는 에러를 반환할 수 있게 된다
Optional 최대 요소 수는 한 개이므로 사용을 난발해서는 안된다