티스토리 뷰

Java/Effective Java

[Item54] null 멈춰

ryumodern 2022. 5. 9. 18:17

Item54에서는 null이 아닌 빈 컬렉션이나 배열을 반환하라 말한다

생각해보면 어떤 객체든 값이 없는 경우 null 반환 때리면 간단한데 왜 하지 말라는 걸까?

null 만든 사람조차 10억 달러짜리 실수라 말했기 때문이다

 

https://www.codebyamir.com/blog/stop-returning-null-in-java#:~:text=%E2%80%9CI%20call%20it%20my%20billion%2Ddollar%20mistake.

 

어떤 메서드든 null을 반환하면 클라이언트 측에서 null check가 필요하다

만약 something 객체가 인스턴스 변수로 참조 타입을 가지고 있고 그 참조를 사용하려 한다면 null check 한방 더 들어간다 

if (something != null)
// 로직 수행

if (something == null)
  throw new 어쩌구Exception();

 

null check로 콜백 지옥과 같은 형태로 뎁스가 쭉쭉 늘어나 진짜 중요한 비즈니스 로직을 가리게 될 수 있고

실수로 빠트린 경우에는 수 많은 null check 사이에서도 NPE가 터질 수 있다

그렇다면 null을 반환하지 않으려면 어째야 하는가?

책의 조언을 따라 빈 컬렉션이나 배열을 반환하자, 완벽하지는 않지만 최선의 방법이다

빈 컬렉션이나 배열을 이용해도 위험한 상황은 컬렉션 & 배열 안의 요소를 직접 다룰 때다

아래와 같이 요소를 다룰 필요가 있을 때는 이 때도 CollectionUtils.isEmpty(), Arrays.size() 등의 체크가 필요하다

list.get(0).어쩌구
array[0].저쩌구

 

요런 상황을 제외하고는 빈 컬렉션에는 Collections.emptyList(), new Array [0]의 형태로 최적화도 가능하다

처음 읽었을 때는 어차피 얘네도 체크가 필요한 것 아닌가 싶었다

근데 단순히 반환된 걸로 향상된 for문 돌릴 때는 요소가 없어 돌아가지 않아, NPE가 터지지 않는 문제 없는 코드임을 알았다

그럼에도 아주 많은 작업을 하는 메서드에서는 early-return으로 약간의 성능 향상을 얻을 수 있다

비어 있는 경우 빨리 끝내버리고 후행 로직을 안 타게 만들면 된다

if (CollectionUtils.isEmpty(list)) {
  return;
}

// 무진장 긴 로직

 

마지막으로 IDE의 힘을 빌려 롬복의 @NonNull, 스프링의 @NotNull, jetbrains의 @NotNull 등을 활성화시키고

메서드의 인자 쪽에 붙여주면 null이 들어갈 수 있는 가능성이 있는 부분에서 경고를 띄워준다

settings -> compiler -> configure annotation에서 설정하면 된다

 

 

아래와 같이 null이 들어오면 안 되는 곳에 @NotNull 혹은 @NonNull 붙이라고 IDE의 경고가 뜬다

이 기능이 나쁘지 않은 것 같아 사용 중이긴 한데 단점으로 인자가 많은 경우 메서드 시그니처가 상당히 더러워진다는 점이 있다

맘에 들진 않지만 코틀린식 매개변수 나열을 하면 그나마 깔끔해진다

 

 

Optional 반환하면 되는데 왜 빈 컬렉션 반환하지라는 의문이 생길 수 있는데

그에 대답으로 아래 댓글을 소개한다

Optional 자체가 null을 대체하기 위해 만들어진 것이 아니고 상황에 따라 쓸 수 있고, 써선 안 되는 경우가 있다

Optional 남발은 안티 패턴이며 얘를 써도 값이 들었는지 비었는지 체크가 필수이기 때문에

성능도 조금 깎아먹고 값 체크는 또 해야 되는 그런 놈이다만 데이터 처리 과정에 체이닝을 할 수 있어 편하긴 하다

 

 

댓글
링크
글 보관함
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Total
Today
Yesterday