>Java >java지도 시간 >Java String의 null 객체에 대한 내결함성 처리 요약

Java String의 null 객체에 대한 내결함성 처리 요약

黄舟
黄舟원래의
2017-03-31 11:07:061593검색

서문

최근 "Thinking in Java"를 읽다가 다음 구절을 보았습니다.

클래스의 필드인 프리미티브는 자동으로 0으로 초기화됩니다. 모든 것은 객체이다 장. 그러나 객체 참조는 null로 초기화되며, 이들 중 하나에 대해 메서드를 호출하려고 하면 런타임 오류가 발생합니다. 편리하게도 null 참조를 발생시키지 않고 인쇄할 수 있습니다. 예외.
주요 아이디어는 기본 유형이 자동으로 0으로 초기화되지만 개체 참조는 null로 초기화된다는 것입니다. 개체의 메서드를 호출하려고 하면 null 포인터 예외가 발생합니다. 일반적으로 예외를 발생시키지 않고 null 개체를 인쇄할 수 있습니다.

첫 번째 문장은 누구나 쉽게 이해할 수 있을 거라 믿습니다. 이는 유형 초기화에 대한 기본 지식이지만 두 번째 문장은 나를 매우 혼란스럽게 만듭니다. null 객체를 인쇄하면 왜 예외가 발생하지 않습니까? 이 질문을 염두에 두고 나는 이해의 여정을 시작했습니다. 아래에서는 이 문제를 해결하기 위한 내 아이디어를 자세히 설명하고 JDK 소스 코드를 분석하여 문제에 대한 답을 찾을 것입니다.

문제 해결 과정

이 문제에는 실제로 여러 가지 상황이 있음을 알 수 있으므로, 카테고리별로 다양한 상황을 논의하여 답을 얻을 수 있는지 알아보겠습니다. 끝.

우선 이 문제를 세 가지 작은 문제로 나누어 하나씩 해결해 나가겠습니다.

첫 번째 질문

null String 객체를 직접 인쇄하면 어떤 결과가 나오나요?

String s = null;
System.out.print(s);

의 결과는

null

가 책에서 말하는 것처럼 예외를 발생시키지 않고 null를 인쇄한다는 것입니다. 분명히 문제의 단서는 print 함수의 소스 코드에 있습니다. print의 소스 코드를 찾았습니다:

public void print(String s) {
    if (s == null) {
        s = "null";
    }
    write(s);
}

소스 코드를 봤을 때 단순한 판단일 뿐이라는 것을 깨달았습니다. 단순한 구현에 조금 실망하셨을 수도 있습니다. JDK. 걱정하지 마십시오. 첫 번째 질문은 단지 전채요리일 뿐이며 잔치는 아직 오지 않았습니다.

두 번째 질문

Integer와 같은 null이 아닌 문자열 개체를 인쇄합니다.

Integer i = null;
System.out.print(i);

작업 결과는 놀랍지 않습니다.

null

print의 소스코드를 살펴보겠습니다.

public void print(Object obj) {
    write(String.valueOf(obj));
}

는 조금 다른 것 같습니다. valueOf에 그 비밀이 숨겨져 있는 것 같습니다.

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

이것을 보고 마침내 예외를 발생시키지 않고 null 개체를 인쇄하는 비결을 발견했습니다. print 메서드는 String 개체와 String이 아닌 개체를 별도로 처리합니다.

  1. 문자열 개체 : null인지 직접 확인합니다. null인 경우 해당 값을 "null"으로 할당합니다.

  2. 문자열이 아닌 객체 : String.valueOf 메서드를 호출하여 null 객체인 경우 "null"를 반환하고, 그렇지 않으면 객체의 toString를 호출합니다. 방법.

위의 처리를 통해 null 개체 인쇄 시 오류가 발생하지 않음을 보장할 수 있습니다.

여기서 이 글을 마무리해야 합니다.
뭐? 약속한 저녁은 어디 있지? 치아 사이에 들어갈 정도로 충분하지 않습니다.
농담이에요. 아래의 세 번째 질문을 살펴보겠습니다.

세 번째 질문(숨겨진 잔치)

Null 객체와 문자열을 연결하면 어떤 결과가 나올까요?

String s = null;
s = s + "!";
System.out.print(s);

결과를 추측하셨을 수도 있습니다.

null!

왜요? 코드 실행을 추적해 보면 이번에는 print과 아무런 관련이 없음을 알 수 있습니다. 그런데 위의 코드는 print 함수를 호출하는데, 또 누구일 수 있을까요? +가 가장 의심스럽습니다. 그런데 +는 함수가 아닙니다. 소스 코드를 어떻게 볼 수 있나요? 이 경우 유일한 설명은 컴파일러가 이를 변조했다는 것입니다. 컴파일러가 생성한 바이트코드를 보면 소스 코드를 찾을 수 없습니다.

L0
 LINENUMBER 27 L0
 ACONST_NULL
 ASTORE 1
L1
 LINENUMBER 28 L1
 NEW java/lang/StringBuilder
 DUP
 INVOKESPECIAL java/lang/StringBuilder.<init> ()V
 ALOAD 1
 INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
 LDC "!"
 INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
 INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
 ASTORE 1
L2
 LINENUMBER 29 L2
 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
 ALOAD 1
 INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/String;)V

위 바이트코드를 읽고 혼란스러우셨나요? 여기서는 주제를 바꿔서 + 스트링 스플라이싱의 원리에 대해 이야기해보겠습니다.

컴파일러는 먼저 StringBuilder을 인스턴스화한 다음 추가된 문자열을 append 순서로 배치하고 마지막으로 toString를 호출하여 String 개체를 반환합니다. 믿을 수 없다면 위의 바이트코드를 보고 StringBuilder이 나타나는지 확인해 보세요. 자세한 설명은 Java 세부 정보: 문자열 접합 문서를 참조하세요.

String s = "a" + "b";
//等价于
StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append("b");
String s = sb.toString();

문제로 돌아가서, 이제 우리는 비밀이 StringBuilder.append 함수의 소스 코드에 있다는 것을 알았습니다.

//针对 String 对象
public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}
//针对非 String 对象
public AbstractStringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

private AbstractStringBuilder appendNull() {
    int c = count;
    ensureCapacityInternal(c + 4);
    final char[] value = this.value;
    value[c++] = &#39;n&#39;;
    value[c++] = &#39;u&#39;;
    value[c++] = &#39;l&#39;;
    value[c++] = &#39;l&#39;;
    count = c;
    return this;
}

이제 append 함수가 개체가 null이라고 판단하면 appendNull를 호출하고 "null"을 채울 것이라는 사실을 갑자기 깨달았습니다.

요약

위에서 Java에서 String null 개체의 내결함성 처리로 이어지는 세 가지 문제를 논의했습니다. 위의 예는 모든 처리 상황을 다루지는 않으며 소개로 간주됩니다.

프로그램에서 null 개체를 어떻게 제어할 수 있는지는 프로그래밍할 때 항상 주의해야 할 사항입니다.

위 내용은 Java String의 null 객체에 대한 내결함성 처리 요약의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.