Stream을 Null Safety하게 사용하기
Java는 Null safety가 중요하다
거두절미하고 이야기하겠다. 당연히 나는 이 코드가 동작할거라 생각했다.
names.stream().filter(Objects::nonNull).forEach(System.out::println);
근데 NPE가 발생한다. 응? 당연히 잘되는게 아닌가 싶지만...
우리는 names가 List 타입인거 까지는 아는데.... 그게 어떤 값일지 모르기 때문에 발생하는 문제이다. 만약 names가 null이라면? → 이때 NPE를 발생하는 것이다.
심지어 이건 JPA에서도 발생하는 문제인데..
이런 방법을 해결하기 위한 방법?
간단하다. Optional로 Wrapping하는 거다.
Optional.ofNullable(names).orElseGet(ArrayList::new)
.stream()
.filter(Objects::nonNull)
.forEach(System.out::println);
더 좀더 Stream을 조금 더 ElseGet을 활용하기 위해서는 이렇게 써도 좋다.
Optional.ofNullable(names).orElseGet(Collections::emptyList)
.stream()
근데 문제는 이게... Stream 사용할때 매번 이렇게 Optional
을 감싸서 쓰는건 매우 귀찮은 일이다.
그럼 함수를 아예 만들어서 사용하자.
public static <T> Stream<T> nullSafeStream(final Collection<T> collection) {
return Optional.ofNullable(collection)
.orElseGet(Collections::emptyList).stream();
}
이런식으로 방어용 Stream을 만들어쓰면 NPE 발생을 막을 수 있다.
왜 사용해야하는가?
이게 Compile Error
로 문제가 터지는게 아니다. 일단 List자체가 null인 경우에 발생하는 것이기 때문에, 무조건 Runtime Exception
이 발생한다. 즉, 내가 null인 상황을 확실히 컨트롤 할 수 있다면야.. 문제가 없다고 보지만...
실무 상황에서 솔직히 null이 안 발생하냐 발생하냐를 완전히 컨트롤 하긴 쉽지 않을거라고 본다. 레거시 코드를 죄다 null이 불가능하도록 코드를 고치거나 해야하는데.. 이건 좀 쉬운 일은 아닐거라 본다. 레거시 코드를 함부로 막 고치다가 엄한곳에서 이상한 오류가 발생하던 경험이 몇번 있어서, 차라리 방어 코드를 설치하는게 좋다고 생각한다.
후일담
JPA에서는 어떤식으로 처리해야지 다음과 같은 상황을 막을 수 있을까 조금씩 수정해서 글좀 작성해보겠다.
출처
https://sigmasabjil.tistory.com/43
https://www.baeldung.com/java-null-safe-streams-from-collections
https://stackoverflow.com/questions/41590134/null-safe-collection-as-stream-in-java-8
http://gist.githubusercontent.com/felipebelluco/defa683a7f9d437488d3a46e72665af2/raw/38ef1aec18eb845aab49023c05c77f59abc0c37f/Main.java
'Java' 카테고리의 다른 글
Slack App Directory를 활용하여 Webhook보다 퀄 좋은 메세지 발송하기 (0) | 2024.05.12 |
---|---|
클린 코드 - 1. 객체 지향 생활 체조 (0) | 2024.03.31 |
Deprecated 잘쓰는 법 (0) | 2023.09.02 |
JWT Expired 시간이 토큰 발급시간보다 이전 시간인 경우 (2) | 2022.08.18 |
Java String + 연산은 정말 빠른가? (0) | 2021.11.21 |