Java 프로그래머에게 null은 골치 아픈 일입니다. NPE(Null Pointer Exceptions)로 인해 괴롭힘을 당하는 경우가 많습니다. Java의 발명가조차도 이것이 자신의 큰 실수라고 인정했습니다. Java가 null을 유지하는 이유는 무엇입니까? Null은 한동안 존재해 왔으며 Java 발명가들은 Null이 해결한 문제보다 더 많은 문제를 야기한다는 것을 알고 있었던 것 같습니다. 그러나 Null은 여전히 Java에 존재합니다.
Java의 디자인 원칙은 모든 것을 단순화하는 것이므로 포인터, 연산자 오버로딩 및 다중 상속 구현에 시간을 낭비하지 않는 이유는 Null이 정반대이기 때문입니다. 글쎄요, 저는 이 질문에 대한 답을 잘 모르겠습니다. 제가 아는 것은 Java 개발자와 오픈 소스 커뮤니티가 null을 아무리 비판하더라도 우리는 null과 공존해야 한다는 것입니다. null의 존재를 후회하기보다는 null에 대해 더 잘 배우고 null이 올바르게 사용되는지 확인해야 합니다.
Java에서 null을 배워야 하는 이유는 무엇입니까? null에 주의를 기울이지 않으면 Java는 NullPointerException으로 인해 어려움을 겪게 되고 고통스러운 교훈을 얻게 되기 때문입니다. 에너지 넘치는 프로그래밍은 팀, 고객, 사용자가 더욱 높이 평가할 예술입니다. 내 경험에 따르면 널 포인터 예외가 발생하는 주된 이유 중 하나는 Java에서 널에 대한 지식이 부족하기 때문입니다. 많은 사람들이 이미 null에 대해 잘 알고 있지만, 그렇지 않은 사람들을 위해 null에 대한 오래되고 새로운 내용을 배울 수 있습니다. Java에서 null에 대한 몇 가지 중요한 지식을 다시 배워 보겠습니다.
Java에서 Null이란 무엇입니까?
앞서 말했듯이 null은 Java에서 매우 중요한 개념입니다. null의 원래 의도는 누락된 사용자, 리소스 또는 기타 항목과 같은 누락된 항목을 나타내는 것입니다. 그러나 1년 후, 골치 아픈 널 포인터 예외로 인해 Java 프로그래머들은 많은 괴롭힘을 당하게 되었습니다. 이 자료에서는 Java의 null 키워드에 대한 기본 세부 사항을 배우고, null 검사를 최소화하는 몇 가지 기술과 불쾌한 null 포인터 예외를 방지하는 방법을 살펴보겠습니다.
1) 우선 null은 Java의 public, static, final과 같은 키워드입니다. 대소문자를 구분하며 null을 Null 또는 NULL로 쓸 수 없으며 컴파일러는 이를 인식하지 못하고 오류를 보고합니다.
다음과 같이 코드 코드를 복사합니다.
객체 obj = NULL; // 괜찮지 않음
객체 obj1 = null //확인
다른 언어를 사용하는 프로그래머라면 이런 문제가 발생할 수도 있지만, 이제 IDE를 사용하면서 이 문제는 사소한 문제가 되었습니다. 이제 코드를 입력하면 Eclipse 및 Netbeans와 같은 IDE가 이 오류를 수정할 수 있습니다. 그러나 메모장, Vim, Emacs와 같은 다른 도구를 사용하면 이 문제는 귀중한 시간을 낭비하게 됩니다.
2) 모든 기본 유형에 기본값이 있는 것처럼, 예를 들어 int의 기본값은 0이고, boolean의 기본값은 false이며, 엄밀히 말하면 null은 모든 참조 유형의 기본값입니다. 모든 객체 유형의 기본값이 false인 부울 변수를 생성하는 것과 마찬가지로 Java의 모든 참조 변수는 기본값으로 null을 갖습니다. 이는 멤버 변수, 지역 변수, 인스턴스 변수, 정적 변수 등 모든 변수에 적용됩니다(그러나 초기화되지 않은 지역 변수를 사용하면 컴파일러에서 경고합니다). 이 사실을 입증하기 위해 다음 코드에 표시된 대로 변수를 만든 다음 해당 값을 인쇄하여 이 참조 변수를 관찰할 수 있습니다.
다음과 같이 코드 코드를 복사합니다.
개인 정적 개체 myObj;
공개 정적 무효 메인(문자열 인수[]){
System.out.println("myObjc의 값은 무엇입니까 : " + myObj);
}
myObjc의 값은 무엇입니까: null
이는 정적 개체와 비정적 개체 모두에 해당됩니다. 여기에서 볼 수 있듯이 myObj를 정적 참조로 정의하여 기본 메서드에서 직접 사용할 수 있도록 했습니다. 기본 메서드는 정적 메서드이므로 비정적 변수를 사용할 수 없습니다.
3) 몇 가지 오해를 명확히 하고 싶습니다. Null은 객체도 아니고 유형도 아닙니다. 어떤 참조 유형에도 할당할 수 있습니다. 아래 코드를 참조하세요.
다음과 같이 코드 코드를 복사합니다.
String str = null; // String에 null을 할당할 수 있습니다.
Integer itr = null; // Integer에도 null을 할당할 수 있습니다.
Double dbl = null; // Double에도 null을 할당할 수 있습니다.
String myStr = (String) null; // null은 String으로 유형 변환될 수 있습니다.
Integer myItr = (Integer) null; // Integer로 유형 변환할 수도 있습니다.
Double myDbl = (Double) null; // 예, 가능합니다. 오류는 없습니다.
컴파일 및 런타임 시 null을 모든 참조 유형으로 캐스팅할 수 있으며 런타임 시 null 포인터 예외가 발생하지 않는다는 것을 알 수 있습니다.
4) 참조 변수에는 Null을 할당할 수 있지만, int, double, float, boolean 등 기본형 변수에는 null을 할당할 수 없습니다. 그렇게 하면 컴파일러는 다음과 같은 오류를 발생시킵니다.
다음과 같이 코드 코드를 복사합니다.
int i = null; // 유형 불일치: null을 int로 변환할 수 없습니다.
short s = null; // 유형 불일치: null을 short로 변환할 수 없습니다.
byte b = null: // 유형 불일치: null을 바이트로 변환할 수 없습니다.
double d = null; //형식 불일치: null을 double로 변환할 수 없습니다.
정수 itr = null; // 괜찮습니다.
int j = itr; // 이것도 괜찮지만 런타임에 NullPointerException이 발생합니다.
보시다시피 기본 유형에 null을 직접 할당하면 컴파일 오류가 발생합니다. 그러나 래퍼 클래스 객체에 null을 할당한 다음 해당 기본 유형에 객체를 할당하면 컴파일러는 이를 보고하지 않지만 런타임 시 null 포인터 예외가 발생합니다. 이는 Java의 자동 언박싱으로 인해 발생하며 다음 글머리 기호에서 살펴보겠습니다.
5) null 값을 포함하는 모든 래퍼 클래스는 Java가 기본 데이터 유형을 unboxing하고 생성할 때 null 포인터 예외를 발생시킵니다. 일부 프로그래머는 오토박싱이 null을 해당 기본 유형의 기본값(예: int의 경우 0, 부울 유형의 경우 false)으로 변환한다고 생각하는 실수를 범하지만, 이는 아래와 같이 올바르지 않습니다.
다음과 같이 코드 코드를 복사합니다.
정수 iAmNull = null;
int i = iAmNull; // 기억하세요 - 컴파일 오류 없음
그러나 위 코드 조각을 실행하면 콘솔에서 메인 스레드가 널 포인터 예외를 발생시키는 것을 볼 수 있습니다. HashMap 및 Integer 키 값을 사용할 때 이러한 오류가 많이 발생합니다. 다음 코드를 실행하면 오류가 나타납니다.
다음과 같이 코드 코드를 복사합니다.
java.util.HashMap 가져오기;
java.util.Map 가져오기;
/**
* Autoboxing 및 NullPointerExcpetion의 예
*
* @author 윈도우 8
*/
공개 클래스 테스트 {
public static void main(String args[])에서 InterruptedException이 발생합니다.
맵 번호AndCount = new HashMap<>();
int[] 숫자 = {3, 5, 7,9, 11, 13, 17, 19, 2, 3, 5, 33, 12, 5};
for(int i : 숫자){
int count = numberAndCount.get(i);
numberAndCount.put(i, count++); // 여기서는 NullPointerException이 발생합니다.
}
}
}
산출:
다음과 같이 코드 코드를 복사합니다.
스레드 "main" java.lang.NullPointerException의 예외
Test.main에서(Test.java:25)
이 코드는 매우 간단하고 오류가 없어 보입니다. 당신이 해야 할 일은 배열에 숫자가 몇 번 나타나는지 알아내는 것뿐입니다. 이는 Java 배열에서 중복 항목을 찾는 일반적인 기술입니다. 개발자는 먼저 이전 값을 가져온 다음 값을 추가하고 마지막으로 값을 다시 맵에 넣습니다. 프로그래머는 put 메소드를 호출할 때 자동 박싱이 int를 Interger로 박싱하는 작업을 처리할 것이라고 생각할 수 있지만, 숫자에 카운트 값이 없으면 HashMap의 get() 메소드가 null을 반환하고 0이 아님을 잊어버립니다. , Integer의 기본값은 0이 아닌 null이기 때문입니다. Autoboxing은 null 값을 int 변수에 전달할 때 NullPointerException을 반환합니다. 이 코드가 if 중첩 내부에 있고 QA 환경에서 실행되지 않았지만 일단 프로덕션 환경에 넣으면 BOOM이 발생한다고 상상해 보세요 :-)
6) null 값이 있는 참조 유형 변수가 사용되는 경우 인스턴스of 작업은 false를 반환합니다.
다음과 같이 코드 코드를 복사합니다.
정수 iAmNull = null;
if(iAmNull 인스턴스of정수){
System.out.println("iAmNull은 Integer의 인스턴스입니다.");
}또 다른{
System.out.println("iAmNull은 Integer의 인스턴스가 아닙니다.");
}
산출:
다음과 같이 코드 코드를 복사합니다.
나
AmNull은 Integer의 인스턴스가 아닙니다.
이는 인스턴스 오브 작업의 매우 중요한 기능으로, 유형 캐스트 검사에 유용합니다.
7) null 값이 있는 참조 유형 변수를 사용하기 위해 비정적 메서드를 호출할 수 없다는 것을 알고 계실 것입니다. null 포인터 예외가 발생하지만 정적 메서드를 사용하여 null 값이 있는 참조 유형 변수를 사용할 수 있다는 사실을 모를 수도 있습니다. 정적 메서드는 정적 바인딩을 사용하므로 null 포인터 예외가 발생하지 않습니다. 예는 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다.
공개 클래스 테스트 {
공개 정적 무효 메인(문자열 인수[]){
myObject 테스트 = null;
myObject.iAmStaticMethod();
myObject.iAmNonStaticMethod();
}
개인 정적 무효 iAmStaticMethod(){
System.out.println("나는 정적 메서드입니다. null 참조로 호출할 수 있습니다.");
}
개인 무효 iAmNonStaticMethod(){
System.out.println("나는 정적 메서드가 아닙니다. null로 나를 호출할 날짜가 없습니다.");
}
산출:
다음과 같이 코드 코드를 복사합니다.
저는 정적 메서드이므로 null 참조로 호출할 수 있습니다.
스레드 "main" java.lang.NullPointerException의 예외
Testing.main에서(Testing.java:11)
8) 메소드에 null을 전달할 수 있으며 메소드는 모든 참조 유형을 수신할 수 있습니다. 예를 들어 public void print(Object obj)는 이와 같이 print(null)을 호출할 수 있습니다. 컴파일 관점에서는 괜찮지만 결과는 전적으로 메서드에 따라 달라집니다. 이 예제의 print 메소드와 같은 Null 안전 메소드는 NullPointerException을 발생시키지 않고 정상적으로 종료됩니다. 비즈니스 로직이 허용한다면 null-safe 메서드를 사용하는 것이 좋습니다.
9) == 또는 != 연산을 사용하여 null 값을 비교할 수 있지만 보다 작거나 큼과 같은 다른 알고리즘이나 논리 연산을 사용할 수 없습니다. SQL과 달리 null==null은 아래와 같이 Java에서 true를 반환합니다.
다음과 같이 코드 코드를 복사합니다.
공개 클래스 테스트 {
public static void main(String args[])에서 InterruptedException이 발생합니다.
문자열 abc = null;
문자열 cde = null;
if(abc == cde){
System.out.println("null == Java에서는 null이 true입니다.");
}
if(널 != 널){
System.out.println("null != null은 Java에서 false입니다.");
}
// 전통적인 널 검사
if(abc==null){
// 뭔가를 해라
}
// 괜찮지 않음, 컴파일 시간 오류
if(abc > null){
}
}
}
산출:
다음과 같이 코드 코드를 복사합니다.
null == Java에서는 null이 true입니다.
이것은 Java의 null에 관한 것입니다. Java 프로그래밍에 대한 경험이 있고 간단한 트릭을 사용하여 Null 포인터 예외를 방지하면 코드를 Null로부터 안전하게 만들 수 있습니다. null은 비어 있거나 초기화되지 않은 값으로 사용되는 경우가 많기 때문에 혼란의 원인이 됩니다. 메소드의 경우 null이 매개변수로 사용될 때 메소드가 어떻게 작동하는지 기록하는 것도 매우 중요합니다. 전체적으로 null은 모든 참조 유형 변수의 기본값이라는 점을 기억하세요. null 참조를 사용하여 Java에서 인스턴스 메서드나 인스턴스 변수를 호출할 수는 없습니다.