Java는 포인터(Pointer)가 없는데 왜 NullPointerException이 발생할까?
1. Java는 포인터(Pointer)가 없는 언어다?
Java의 특징을 이야기 할 때 포인터(Pointer)가 없는 언어라고 이야기한다.
근데 여기서 포인터란 무엇일까?
포인터란 c언어에서 주로 사용되는 개념으로 메모리의 주소값을 저장하는 변수이다.
포인터 : 메모리의 주소값을 저장하는 변수, 어떤 이름(label)이 메모리의 어떤 주소를 가리키고 있는지에 대한 정보
// c/c++
int a = 3;
int *p = &a; //a 변수의 메모리 주소 번지
그렇다면 Java에는 왜 포인터가 없다고 하는 것일까?
Java에서는 포인터라는 개념대신 참조(Reference)라는 개념을 사용한다.
참조나 포인터나 둘 다 객체의 주소를 가리키고 접근할 수 있다는 점은 똑같다.
하지만 둘의 핵심적인 차이는, "포인터는 메모리 주소를 직접 다룰 수 있지만, 참조는 할 수 없다"는 것이다.
포인터는 주소 값을 임의의 메모리 주소로 변경할 수 있다.
만약 개발자가 실수로 주소 값을 변경해버리면 segment fault 같은 문제가 발생할 가능성이 생기게 된다.
하지만 참조는 직접 메모리에 접근이 불가능하기 때문에 주소 값을 임의의 메모리 주소로 변경할 수 없다.
물론 직접적으로 메모리에 접근이 불가능한 것이지 new 키워드로 생성한 경우 내부적으로는 메모리 주소에 접근한다.
즉, 포인터를 사용하면 유연성과 성능을 향상시킬 수 있지만 안정성이 떨어지기 때문에 Java에서는 포인터라는 개념을 개발자에게 제공하지 않고 참조를 사용하고 있다. 이때문에 Java를 포인터가 없는 언어라고 하는 것이다.
그렇다면 Java에서 NullPointerException은 왜 발생하는 것일까?
2. NullPointerException이란?
Java 개발을 하다보면 NullPointerException을 자주 만날 수 있게 된다.
NullPointerException은 null 때문에 발생하는 RuntimeException이다.
Java에서 NullPointerException은 위에서 살펴본 참조라는 개념때문에 나타나게 된다.
Java의 자료형에는 기본형과 참조형이 있다. 기본형의 기본 값은 0이지만 참조형의 기본값은 null이다.
그렇기 때문에 참조형은 객체를 생성하기 전까지는 할당된 메모리 주소가 없는 null 값을 참조하게 되고 이를 호출하려고 하면 NullPointerException이 발생하게 된다.
<NullPointerException이 발생하는 경우>
- null 객체에서 method를 호출하는 경우
- null 객체의 필드에 접근하거나 값을 변경하는 경우
- null의 길이를 배열처럼 취하는 경우
- null을 throw 하는 경우
- null을 통해 동기화 할 경우
이러한 NullPointerException을 만나지 않으려면 어떻게 해야 할까?
1) null이 발생할 것 같은 값에 대해서는 미리 예측해서 null체크를 해주기
여기서 중요한 점은 if문에 여러 조건을 같이 체크한다면 null체크를 먼저 하기!
if(str.equals("a") || str!=null){
}// x
if(str!=null || str.equals("a")){
}// o
2) chaning메서드 호출 자제하기
str.a(). b() -> 이런 식의 연결된 메서드 호출은 중간에 어떤 값이 return 될지 모르니 안전하게 사용하기 위해 자제하는 것이 좋다.
String city = getPerson(id).getAddress().getCity();
3) toString() 대신 String.valueOf() 사용하기
toString은 NullPointerException이 발생하고 String.valueOf()는 null 스트링 값 자체가 리턴된다.
Integer i = null;
System.out.println(String.valueOf(i));// -> null
System.out.println(i.toString());//-> NullPointerException
4) Try-Catch 사용하기
public class main {
public static void main(String[] args){
try {
String str = null;
System.out.println(str.toString());
}catch (NullPointerException e) {
System.out.println("--NullPointerException 발생--");
System.out.println("기존 코드를 체크해 주세요!!");
}finally {
System.out.println("예외처리 코드가 오류없이 진행되었습니다.");
}
}
}
5) null을 Parameter로 넘기지 말 것
6) Java 8 이상에서는 Optional을 사용
참고 :
https://rainbow97.tistory.com/entry/JAVA-NullPointerException-%EC%B2%98%EB%A6%AC%EB%B0%A9%EB%B2%95
'Java' 카테고리의 다른 글
해시맵(HashMap)이란? (0) | 2023.01.11 |
---|---|
클래스 변수(Class variable) vs 인스턴스 변수(Instance variable) vs 지역 변수(local variable) (0) | 2022.12.31 |
0.1이 진짜 0.1이 아닌 이유(부동소수점(Floating Point)) (0) | 2022.12.13 |
JAVA 자료형 (0) | 2022.02.22 |
Java의 언어적 특징 (0) | 2022.02.21 |