GDGoC 백엔드 과제 2주차 피드백 내용 중 탐구해 본 NPE 처리 방법 정리 글 입니다
과제 내용 (내 구현)
findStudentByPart()
- 파라미터로 파트명을 전달받아, 그 파트의 학생 하나를 반환하는 메서드
- 메서드 내부에서 Stream을 사용해야 합니다.
@Override
public Optional<Student> findStudentByPart(String part) {
return studentsMap.values().stream()
.filter(student -> student.getPart().equals(part))
.findFirst();
}
- studentsMap에 저장된 모든 Student 객체를 순회
- part 값이 같은 학생만 필터링
- 그중 첫 번째 학생만
Optional<Student>로 반환
피드백 내용
만약 Main 함수에서
sd.addStudent(5, new Student("김태우", 27, null, "1999-12-12"));
이와 같은 코드가 있었다면, part가 null 이므로 예외가 발생하지 않았을까요?
예외가 발생한다면, 어떻게 처리할 수 있을까요?
이번 과제의 규격을 벗어날 수 있는 질문이지만, 정혁님이라면 충분히 고민해 볼 만한 주제라고 생각합니다!
- Main 함수에서 학생 정보로 학생 인스턴스 생성하는 과정에서 null 값이 입력된다면 NPE 발생
- NPE가 발생하지 않도록 구현체에서 안전하게 처리할 수 있는 방법을 찾아보자!
sol 1) Objects.equals 사용으로 null 처리
@Override
public Optional<Student> findStudentByPart(String part) {
return studentsMap.values().stream()
.filter(student -> Objects.equals(student.getPart(), part))
.findFirst();
}
코드 흐름
.filter(student -> Objects.equals(student.getPart(), part))Objects.equals(a, b)는 a 또는 b가 null이어도 안전하게 동작함- 학생의 part 값이 입력받은 part와 같은지 비교합니다
- .findFirst()일치하는 학생이 없으면 Optional.empty()가 됩니다
- 조건에 맞는 첫 번째 학생을
Optional<Student>로 반환합니다.
student.getPart().equals(part) : student.getPart()가 null이면 NPE 발생!
Objects.equals(student.getPart(), part) : null 안전하게 비교 가능
코드도 단순하고, Optional<Student> 와 함께 쓰면 “찾을 수도 있고 못 찾을 수도 있는 상황”을 확실하게 표현할 수 있을 것 같습니다!
Sol2 ) Optional을 활용한 null 처리
@Override
public Optional<Student> findStudentByPart(String part) {
return studentsMap.values().stream()
.filter(student -> Optional.ofNullable(student.getPart())
.map(p -> p.equals(part))
.orElse(part == null))
.findFirst();
}
코드 흐름
Optional.ofNullable(student.getPart())student.getPart()가 null이면 Optional.empty()가 되고, 그렇지 않으면 Optional.of(value)가 됩니다- 학생의 part 값이 null일 수도 있으므로 Optional로 감쌉니다
.map(p -> p.equals(part))결과는 true 또는 false- part 값이 존재한다면, 입력받은 part와 비교합니다
.orElse(part == null)이때 part도 null이면 true, 아니면 false- 만약 student.getPart()가 null이었다면, 이 구문으로 옵니다
.findFirst()- 조건에 맞는 첫 번째 학생을
Optional<Student>로 감싸 반환하게 됩니다 - 없다면 Optional.empty()
- 조건에 맞는 첫 번째 학생을