11장 null 대신 Optional 클래스
보수적인 null 처리법
public String getCarInsuranceName(Person person) {
if (person != null) {
Car car = person.getCar();
if (car !=null) {
Insurance insurance = car.getInsurance();
if (insurance !=null) {
return insurance.getName();
}
}
}
}
returrn "Unknown";
}
- 365p
null 때문에 발생하는 문제
- 에러의 근원이다
- 코드를 어지럽힌다
- 아무 의미가 없다
- 자바 철학에 위배된다
- 형식 시스템에 구멍을 만든다
- 367p
값이 있으면 Optional 클래스는 값을 감싼다. 반면 값이 없으면 Optional.empty 메서드로 Optional을 반환한다. Optional.empty는 Optional의 특별한 싱글턴 인스턴스를 반환하는 정적 팩토리 메서드다.
- 369p
기존 코드
public class Person {
private Car car;
public car getCar(){
return car;
}
}
public class Car {
private Insurance insurance;
public Insurance getInsurance() {
return insurance;
}
}
public class Person {
private Optional<Car> car;
public Optional<Car> getCar() {
return car;
}
}
사람이 차를 소유했을 수도 소유하지 않았을 수도 있으므로 Optional로 정의한다.
- 369 ~ 370p
Optional 만들기 3가지 방식
빈 Optional
Optional<Car> optCar = Optional.empty();
null이 아닌 값으로 Optional 만들기
Optional<Car> optCar = Optional.of(car);
null 값으로 Optional 만들기
Optional<Car> optCar = Optional.ofNullable(car);
- 371p
Optional이 비어있는지 확인하고 반환하기
String name = null;
if (insurance != null) {
name = insuranc.getName();
}
Optional의 map 메서드 사용하기
Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);
flatMap을 이용해서 하나의 스트림으로 병합하여 평준화할 수 있듯이 optional에도 적용될 수 있다.
public String getCarInsuranceName(Optional<Person> person) {
return person.flatMap(Person::getCar)
.flatMap?(Car::Insurance)
.map(Insurance::getName)
.orElse("Unknown");
}
- 375p
public String getCarInsuranceName(Optional<Person> person) {
return person.filter(person -> person.getAge() >= minAge)
.flatMap(Person::getCar)
.flatMap?(Car::Insurance)
.map(Insurance::getName)
.orElse("Unknown");
}
- 383p
null 일 수 있는 값을 optional로 안전하게 변환하기
Optional<Object> value = Optional.ofNullable(map.get("key"));
- 384p
예외를 발생시키는 대신 optional을 반환하도록 할 수 있다.
public static Optional<Integer> stringToInt(String s) {
try {
return Optional.of(Integer.parseInt(s));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
- 385p
프로퍼티에서 지속 시간을 읽는 명령형 코드
public int readDuration(Properties props, String name) {
String value = props.getProperty(name);
if (value != null) {
try {
int i = Integer.parseInt(value);
if (i>0) {
return i;
}
}
} catch (NumberFormatException nfe) { }
}
return 0;
}
=> 요청한 이름이 존재하는지 확인하고 문자를 숫자로 변환하기 위해 시도하고 양수이면 리턴하고 하나의 조건이라도 실패하면 0을 반환한다.
이를 하나의 유연한 코드로 재구현하면
public int readDuration(Properties props, String name) {
return Optional.ofNullable(props.getProperty(name))
.flatMap(OptionalUtility::stringToInt)
.filter(i -> i > 0)
.orelse(0);
}
- 387 ~ 388p
'Book' 카테고리의 다른 글
[독서 기록] 모던 자바 인 액션 13장, 디폴트 메서드 (0) | 2023.01.11 |
---|---|
[독서 기록] 모던 자바 인 액션 12장, 새로운 날짜와 시간 api (0) | 2023.01.11 |
[독서 기록] 모던 자바 인 액션 10장 람다를 이용한 도메인 전용 언어 (0) | 2023.01.10 |
[독서 기록] 모던 자바 인 액션 9장 리팩터링, 테스팅, 디버깅 (0) | 2023.01.10 |
[독서 기록] 모던 자바 인 액션 8장 컬렉션 API 개선 (0) | 2023.01.09 |