이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.
기초개념 › Java
null은 무엇이고, 왜 NullPointerException이 나는가
변수 name에는 문자열 같은 객체 자체가 아니라, 그 객체를 가리키는 값(참조)이 담깁니다. null은 이 자리에 "아무 객체도 가리키지 않는다"를 담는 특별한 값이고, 코드에서는 String name = null;처럼 씁니다. name.length()에서 점(.)은 name이 가리키는 객체에게 일을 시킨다는 표시인데, null이면 시킬 객체가 없어서 NullPointerException이라는 예외가 납니다. if (name != null)은 name이 객체를 가리키는지 먼저 묻는 확인입니다. 글자가 하나도 없는 빈 문자열 ""는 null이 아니라 글자가 0개인 문자열 객체입니다. 이 실습은 name에 담는 값을 "kim", null, ""로 바꾸고 if 확인을 붙였다 떼며 같은 코드를 컴파일하고 실행해, 무엇이 출력되고 예외가 나는지를 봅니다.
실행으로 대조 · JDK 21에서 여섯 가지 조합을 javax.tools로 컴파일하고 java로 실행해 대조
public class Main {
public static void main(String[] args) {
// 변수: 문자열 객체를 가리키거나, null이면 아무것도 가리키지 않는다
String name = "kim";
System.out.println(name.length());
}
}
컴파일러와 실행 환경은 JDK 21.0.12.1(javac 21, java 21)입니다. 여섯 가지 조합을 모두, 화면의 코드와 같은 소스(줄 단위로 같은 글)를 javax.tools로 컴파일하고, 컴파일된 Main을 새 java 프로세스로 실행해 표준 출력, 표준 오류의 첫 줄, 종료 코드를 잡은 결과와 대조했습니다. 대조한 것은 컴파일 성공 여부, 출력, 예외가 났는지(표준 오류의 첫 줄이 NullPointerException인지)와 예외가 난 줄(스택 추적이 가리킨 줄이 name.length() 줄), 종료 코드입니다. 표의 "length() 실행"은 출력에 글자 수가 나왔는지로, "if 확인"은 어느 블록의 출력이 나왔는지로 실제 출력에서 가려냈습니다. 단계 문장이 기대는 사실은 별도 프로그램으로 확인했습니다. 값 세 개 각각에 대해 name == null이 "kim"은 false, null은 true, ""는 false이고 length()는 3, (null이라 부를 수 없음), 0인 것, 그리고 String name = null; 줄은 예외 없이 실행되고 예외는 그다음 name.length() 줄에서 나며 프로그램이 종료 코드 1로 끝나는 것입니다. 문서는 직접 열어 확인했습니다. null 타입의 값은 null 참조 하나뿐이고 어떤 참조 타입에도 담을 수 있다는 것은 Java Language Specification(Java SE 21) 3.10.8절과 4.1절, 참조 값은 객체를 가리키거나 아무 객체도 가리키지 않는 null 참조라는 것은 4.3.1절, 참조를 ==와 !=로 비교하는 규칙은 15.21.3절, if문이 조건이 true이면 첫 번째 문장을, false이면 else의 문장을 실행한다는 것은 14.9.1절과 14.9.2절, 문자열 리터럴이 실행할 때 String 객체를 가리키는 값이고 ""가 빈 문자열이라는 것은 3.10.5절을 따랐습니다. NullPointerException API 문서는 null인 객체의 인스턴스 메서드를 부를 때 던져진다고 적고 있고(Java SE 21 API), String.length()와 isEmpty()의 설명도 같은 API 문서에서 열어 확인했습니다. 인스턴스 메서드 호출에서 대상이 null이면 NullPointerException이 난다는 문장은 JLS 15장(15.6절)의 것을 확인했고, 호출 처리를 자세히 정한 15.12.4.1절과 15.12.4.4절은 본문을 열지 못했습니다. 이 PC의 javac는 변수 이름을 클래스 파일에 넣지 않아 NullPointerException의 상세 메시지에 name 대신 <local1>이 찍혔는데, 이 메시지는 명세가 정한 것이 아니라 이 JDK에서 관찰한 것이어서 화면에는 쓰지 않았습니다. 화면의 코드는 실제로 컴파일되는 모양 그대로이고 줄인 것이 없습니다. 이 밖에 int 같은 기본형 변수와 null, 배열이나 필드가 처음에 null인 것, 두 문자열을 ==와 equals로 견주는 것, null일 수 있는 값을 Optional로 다루는 방법은 다루지 않았고, Optional은 "세부 동작 실습: Optional"에서 다룹니다.
줄을 그은 곳은 처음 코드에서 지운 것이고, 색을 칠한 곳은 새로 쓴 것입니다.