String.valueOf (null)이 NullPointerException을 발생시키는 이유는 무엇입니까?


127

설명서에 따르면이 메서드 String.valueOf(Object obj)는 다음을 반환합니다.

인수가이면 null문자열과 "null"; 그렇지 않으면의 값 obj.toString()이 반환됩니다.

그러나 이것을 시도 할 때 어떻게됩니까?

System.out.println("String.valueOf(null) = " + String.valueOf(null));

대신 NPE를 던지나요? (믿지 않으면 직접 시도하십시오!)

    스레드 "main"의 예외 java.lang.NullPointerException
    java.lang.String. (알 수없는 소스)
    java.lang.String.valueOf (알 수없는 소스)

어떻게 이런 일이 일어나고 있습니까? 문서가 나에게 거짓말입니까? Java의 주요 버그입니까?

답변:


201

문제는 String.valueOf메소드가 오버로드 된다는 것입니다 .

Java Specification Language는 이러한 종류의 경우 가장 구체적인 과부하 가 선택되도록 요구합니다.

JLS 15.12.2.5 가장 구체적인 방법 선택

둘 이상의 멤버 메소드가 액세스 가능하고 메소드 호출에 적용 가능한 경우, 런타임 메소드 디스패치에 대한 설명자를 제공 할 멤버를 선택해야합니다. Java 프로그래밍 언어는 가장 구체적인 방법을 선택 한다는 규칙을 사용합니다 .

A는 char[] -입니다 Object ,하지만 모든 Object 입니다-A char[] . 따라서, char[]더 구체적인 것보다 Object, 그리고 자바 언어에 의해 지정된대로 String.valueOf(char[])과부하이 경우 선택됩니다.

String.valueOf(char[])는 배열이 아닌 것으로 예상하고 null, null이 경우 주어진 이후에을 던진다 NullPointerException.

쉬운 "수정"은 다음과 같이 null명시 적으로 캐스팅하는 Object것입니다.

System.out.println(String.valueOf((Object) null));
// prints "null"

관련 질문


이야기의 교훈

몇 가지 중요한 것들이 있습니다.

  • 효과적인 Java 2 판, 항목 41 : 신중하게 과부하 사용
    • 과부하가 걸린다고해서 항상 매번해야하는 것은 아닙니다
    • 혼란을 일으킬 수 있습니다 (특히 방법이 크게 다른 경우)
  • 좋은 IDE를 사용하면 컴파일 타임에 어떤 과부하가 선택되었는지 확인할 수 있습니다
    • 이클립스를 사용하면 위의 발현에 마우스 호버를 할 수 있고 볼 valueOf(char[])과부하를 선택!
  • 때로는 명시 적으로 캐스팅하고 싶을 때가 있습니다 null(예제)

또한보십시오


캐스팅시 null

null특정 참조 유형 으로 명시 적으로 캐스트해야하는 두 가지 상황 이 있습니다.

  • 과부하를 선택하려면 (위의 예에서와 같이)
  • nullvararg 매개 변수에 단일 인수로 제공하려면

후자의 간단한 예는 다음과 같습니다.

static void vararg(Object... os) {
    System.out.println(os.length);
}

그러면 다음을 가질 수 있습니다.

vararg(null, null, null); // prints "3"
vararg(null, null);       // prints "2"
vararg(null);             // throws NullPointerException!

vararg((Object) null);    // prints "1"

또한보십시오

관련 질문


5
또 다른 제안 : 메소드를 오버로드하고 두 개의 과부하 ( null이 경우 와 같이) 에서 하나의 인수를 호출 할 수 있으면 두 과부하 가 해당 값과 동일하게 작동하는지 확인하십시오!
Joachim Sauer

3
@Joachim : 방금 항목을 읽었으며이 두 가지 방법이 명시 적으로 논의되었다는 사실에 놀랐습니다! 블로흐는 한 단계 더 가서 주장 그 이후 String.valueOf(Object)valueOf(char[])(상관없이 어쨌든 완전히 다른 일을 null하거나하지 않음) 아마도 그들이 처음에 오버로드되지 않았을 것을.
polygenelubricants

질문이 있습니다 ... Object를 반환하는 메서드가 있으면 명령문 return null;과 정확히 같은 것 return (Object) null;입니까?
user972276

17

문제는 당신이 전화하고 있다는 것입니다 String.valueOf(char[])없습니다 String.valueOf(Object) .

그 이유는 Java가 항상 제공된 매개 변수와 작동하는 가장 특정한 오버로드 된 메소드 버전을 선택하기 때문입니다. 매개 변수 null의 유효한 값 Object이지만 매개 변수의 유효한 값이기도합니다 char[].

Java가 Object버전을 사용하게하려면 null변수 를 통해 전달 하거나 Object에 명시 적 캐스트를 지정하십시오.

Object o = null;
System.out.println("String.valueOf(null) = " + String.valueOf(o));
// or
System.out.println("String.valueOf(null) = " + String.valueOf((Object) null));

5

4867608 로 번호가 매겨진 버그 는 2003 년에이 방법으로 제출 되었으며이 설명과 함께 "수정되지 않음"으로 해결되었습니다.

호환성 제약으로 인해이를 변경할 수 없습니다. 이 메소드는 호출되는 최종 정적 String valueOf (char data []) 메소드이며 널 (null) 인수에 대한 "널 (null)"대체를 언급하지 않습니다.

@ ###. ### 2003-05-23


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.