11장

1. null로 발생하는 문제

자바에서 null 참조르 사용하면 다음과 같은 문제가 발생한다.

  • 에러의 근원: NullPointerException은 자바의 가장 흔한 에러

  • 코드 가독성 저하: 중첩된 null 확인 코드로 인해 가독성이 떨어짐

  • 아무 의미가 없음: 정적 형식 언어에서 X을 표현하는 방법으로 적절하지 않음

  • 자바 철학에 위배: 자바는 (null 포인터를 제외한) 모든 포인터를 숨김

  • 형식 시스템에 구멍을 만듦: null은 무형식이라 모든 참조 형식에 할당할 수 있음

2. Optional 클래스

자바 8은 하스켈과 스칼라의 영향을 받아 java.util.Optional<T>라는 새로운 클래스를 제공한다. Optional은 선택형 값을 캡슐화하는 클래스다. Optional 클래스는 값이 있으면 값을 감싸고 없으면 Optional.empty 메서드로 Optional을 반환한다.

png

Optional 형식을 이용하면 도메인 모델의 의미를 더 명확하게 만들 수 있고 null 참조 대신 값이 없는 상황을 표현할 수 있다.

2.1. Optional 적용 패턴

// 빈 Optional 생성
Optional<Car> optCar = Optional.empty();

// null이 아닌 값으로 Optional 생성
Optional<Car> optCar = Optional.of(car);

// null 값으로 Optional 생성
Optional<Car> optCar = Optional.ofNullable(car);

2.2. map과 flatMap

Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);

Optional의 map 메서드는 스트림의 map 메서드와 비슷하다. Optional 객체를 최대 요소의 개수가 한 개 이하인 데이터 컬렉션으로 생각해보자. 스트림의 map은 스트림의 각 원소에 제공된 함수를 적용한다. Optional의 map은 Optional에 포함된 원소에 제공된 함수를 적용한다. 이 과정을 그림으로 나타내면 다음과 같다.

png

Optional의 flatMap 메서드 또한 스트림의 flatMap 메서드와 비슷하다. 스트림의 flatMap 메서드는 함수를 적용해서 생성된 모든 스트림을 하나의 스트림으로 병합해서 평준화한다. Optional의 flatMap도 중첩 Optional을 일차원 Optional로 평준화한다. 이 과정을 그림으로 나타내면 다음과 같다.

png

2.3. Optional 스트림 조작

자바 9에서는 Optional을 포함하는 스트림을 쉽게 처리할 수 있도록 Optional에 stream() 메서드를 추가했다. Optional 스트림을 값을 가진 스트림으로 변환할 때 사용할 수 있다.

public Set<String> getCarInsuranceNames(List<Person> persons) {
    return persons.stream()
                    .map(Person::getCar)
                    .map(optCar -> optCar.flatMap(Car::getInsurance))
                    .map(optIns -> optIns.map(Insurance::getName))
                    .flatMap(Optional::stream)
                    .collect(toSet());
}

3. Optional 클래스의 메서드

메서드
설명

empty

O

빈 Optional 인스턴스 반환

X

filter

O

프레디케이트와 일치하면 값을 포함하는 Optional 반환

X

빈 Optional 반환

flatMap

O

인수로 제공된 함수를 적용한 결과 Optional 반환

X

빈 Optional 반환

get

O

Optional이 감싸고 있는 값 반환

X

NoSuchElementException 발생

ifPresent ifPresentOrElse

O

지정된 Consumer 실행

X

아무 일도 일어나지 않음

isPresent

O

true 반환

X

false 반환

map

O

매핑 함수를 적용

X

-

of

O

값을 감싸는 Optional 반환

X(null)

NullPointerException 발생

ofNullable

O

값을 감싸는 Optional 반환

X

빈 Optional 반환

or

O

같은 Optional 반환

X

Supplier에서 만든 Optional 반환

orElse

O

값을 반환

X

기본값을 반환

orElseGet

O

값을 반환

X

Supplier에서 제공하는 값을 반환

orElseThrow

O

값을 반환

X

Supplier에서 생성한 예외를 발생

stream

O

값만 포함하는 스트림 반환

X

빈 스트림 반환

참고 자료

  • 모던 자바 인 액션 - 한빛미디어

Last updated