NullPointerException
택배를 보낼 때 주소지 없이 택배를 발송하려면 어떤 문제가 발생할까요?
만약 참조값 없이 객체를 찾아가면 어떤 문제가 발생할까요?
- 이 경우
NullPointerExecption이라는 예외가 발생하는데, 개발자를 가장 많이 괴롭히는 예외입니다. -
NullPointerExecption은 이름 그대로null을 가리리키다(Pointer)인데, 이때 발생하는 예외(Exception)입니다. -
null은 없다는 뜻이므로 결국 주소가 없는 곳을 찾아갈 때 발생하는 예외입니다. - 객체를 참조할 때는
.(dot)을 사용합니다.- 이렇게 하면 참조값을 사용해서 해당 객체를 찾아갈 수 있습니다.
- 그런데 참조값이
null이라면 값이 없다는 뜻이므로, 찾아갈 수 있는 객체(인스턴스)가 없습니다.-
NullPointerExecption은 이처럼null에.(dot)을 찍었을 때 발생합니다.
-
예제를 통해서 확인해봅시다.
package ref;
public class NullMain2 {
public static void main(String[] args) {
Data data = null;
data.value = 10; // NullPointerException 예외 발생
System.out.println("data = " + data.value);
}
}
-
data참조형 변수에는null값이 들어가 있습니다.- 그런데
data.value = 10이라고 하면 어떻게 될까요?
- 그런데
data.value = 10;
null.value = 10 // data에는 null 값이 들어있습니다.
- 결과적으로
null값은 참조할 주소가 존재하지 않는다는 뜻입니다.- 따라서 참조할 객체 인스턴스가 존재하지 않으므로 다음과 같이
java.lang.NullPointerExecption이 발생하고, 프로그램이 종료됩니다.참고로 예외가 발생했기 때문에 그 다음 로직은 수행되지 않습니다.
- 따라서 참조할 객체 인스턴스가 존재하지 않으므로 다음과 같이
실행 결과
Exception in thread "main" java.lang.NullPointerException: Cannot assign field "value" because "data" is null at ref.NullMain2.main(NullMain2.java:7)
멤버 변수와 null
앞선 예제와 같이 지역 변수의 경우에는 null 문제를 파악하는 것이 어렵지 않습니다.
- 다음과 같이 멤버 변수가
null인 경우에는 주의가 필요합니다.
Data
package ref;
public class Data {
int value;
}
BigData
package ref;
public class BigData {
Data data;
int count;
}
-
BigData클래스는Data data,int count두 변수를 가집니다.
NullMain3
package ref;
public class NullMain3 {
public static void main(String[] args) {
BigData bigData = new BigData();
System.out.println("bigData.count=" + bigData.count);
System.out.println("bigData.data=" + bigData.data);
// NullPointerException
System.out.println("bigData.data.value=" + bigData.data.value);
}
}
실행 결과
bigData.count=0
bigData.data=null
Exception in thread "main" java.lang.NullPointerException: Cannot read field "value" because "bigData.data" is null at ref.NullMain3.main(NullMain3.java:11)
BigData를 생성하면 BigData의 인스턴스가 생성됩니다.
이때 BigData 인스턴스의 멤버 변수에 초기화가 일어나는데, BigData의 data 멤버 변수는 참조형이므로 null로 초기화 됩니다.
count 멤버 변수는 숫자이므로 0으로 초기화가 됩니다.
-
bigData.count를 출력하면0이 출력됩니다. -
bigData.data를 출력하면 참조값인null이 출력됩니다. 이 변수는 아직 아무것도 참조하고 있지 않습니다. -
bigData.data.value를 출력하면data의 값이null이므로null에.(dot)을 찍게 되고, 따라서 참조할 곳이 없으므로NullPointerException예외가 발생하게 됩니다.
예외 발생 과정
bigData.data.value
x001.data.value // bigData는 x001 참조값을 가집니다.
null.value // x001.data는 null 값을 가집니다.
NullPointerExecption // null 값에 .(dot)을 찍으면 예외가 발생합니다.
“이 문제를 해결하려면 Data 인스턴스를 만들고 BigData.data 멤버 변수에 참조값을 할당하면 됩니다.”
NullMain4
package ref;
public class NullMain4 {
public static void main(String[] args) {
BigData bigData = new BigData();
bigData.data = new Data();
System.out.println("bigData.count=" + bigData.count);
System.out.println("bigData.data=" + bigData.data);
System.out.println("bigData.data.value=" + bigData.data.value);
}
}
실행 결과
bigData.count=0
bigData.data=ref.Data@3a71f4dd
bigData.data.value=0
실행 과정
bigData.data.value
x001.data.value // bigData는 x001 참조값을 가집니다.
x002.value // x001.data는 x002 값을 가집니다.
0 // 최종 결과
참고:
xoo1과x002는sudo code입니다.
정리
- “
NullPointerException이 발생하면null값에.(dot)을 찍었다고 생각하면 문제를 쉽게 찾을 수 있습니다.”