NullPointException을 예방하는 방법과 많이 하는 실수

NullPointException이란?

null 때문에 생기는 exception이다. 객체의 값이 null인 걸 모르는 상태로 이 객체를 다른 곳에 활용하거나 값을 비교하려고 할 때 흔히 볼 수 있다. 다른 예외들에 비해 비교적 덜 무서운(?) 예외지만 그만큼 더 빈번하게 만나게 된다.


NullPointException을 방지하려면

1. NPE 방지용으로 가장 많이 사용하는 != null

Person harang = new Person();
String myName = null;
harang.setName(myName); 

    if(harang.getName() != null){
        System.out.println("이름이 있습니다.");
    }

+) 초보자들이 한 번씩 하는 실수

if(harang!=null && harang.getName().equals("하랑")){
  System.out.println("하랑입니다.");
}else{
  System.out.println("하랑이 아닙니다.");
}  

이 코드를 실행하면 if문 안에서 NPE가 발생한다. !=null으로 방어 코드도 작성했는데 왜 안될까?
harang은 이미 new Person()을 통해 하나의 객체가 생성되어 있기 때문이다. 비어있는 harang 객체의 값을 조회해보면 null이 아니라 Person{name='null', age=0, position='null'}이 출력된다. 위 코드에서 null 비교를 하려면 harang.getName() != null 등으로 값을 꺼내서 비교해야 NPE가 발생하지 않는다.

2. 문자열 비교는 null이 아닌 객체(or 문자열)을 기준으로

 if(harang!=null && ("harang2").equals(harang.getName())){
    System.out.println("하랑입니다.");
}else{
    System.out.println("하랑이 아닙니다.");
}


3. 메소드 체이닝을 남발하지 말자
객체.메소드().메소드().메소드(); 이런 식으로 코드를 쓰면 코드량 자체는 줄어들고, 어딘지 좀 있어보이기도:smirk: 하지만 이 구조에서 NPE가 발생하면 어디가 문제인지 찾기가 훨씬 어려워진다. 그러니까 메소드 체이닝은 NPE가 발생할 일이 없는 게 확실한 경우에만 사용하는 게 바람직하다.

4. 객체 초기화는 빈 값으로 하기

String myName = null;  
String myName2 = "";

위에서 myName을 null로 초기화 했었다. 하지만 myName2처럼 공백으로 초기화를 하면 myName에 값이 들어가지 않은 상태로 호출되어도 NPE는 발생하지 않는다. 소형기기 대상의 프로젝트가 아니라면 이 정도로 메모리 걱정을 할 필요는 없으므로, 꼭 필요한 경우가 아니라면 객체 초기화는 빈 값으로 하면 좋다.


5. 좀 더 강화된 NULL 체크

 if(harang.getName()!=null){ //내용 
 } 

보통 NULL체크를 할 때는 1번 방법으로만 체크하기 보다는 공백인 경우까지 같이 체크한다. 그래서 다음과 같이 쓰는 경우를 더 많이 보았을 것이다.

if(harang.getName() != null && !harang.getName().equals("")){ //내용  
}

이런 식으로 공백 여부까지 체크하는 NULL 체크는 equals를 사용한 비교 뿐만 아니라 param.length==0 이나, param.isEmpty()도 사용이 가능하다. 대체로 처리 시간은 length > isEmpty > equals 순으로 빠르고, length와 equals는 거의 두 배 차이가 난다. 두 배 차이라고 해도 요즘 컴퓨터들의 사양으로는 미세한 수준이지만 처리 속도에 신경을 써야 하는 환경이라면 length를 사용해서 체크하는 것도 괜찮을 것 같다(어려운 것도 아니니까).

if(harang.getName() != null && harang.getName().length()!=0){ //내용 
}

6.스프링을 사용하고 있다면 @NotNull / @NonNull 애노테이션 사용하기
DTO에 @NotNull이나 @NonNull 애노테이션을 사용하면 Null이 들어가는 경우를 방지할 수 있다. 전자는 제트브레인에서, 후자는 롬복에서 제공하는 애노테이션으로 둘 다 자동으로 null체크를 해 준다는 점은 같다.

**7. Optional 사용하기(따로 포스팅 예정) **