[java] Boolean.valueOf ()는 때때로 NullPointerException을 생성합니다.

이 코드가 있습니다.

package tests;

import java.util.Hashtable;

public class Tests {

    public static void main(String[] args) {

        Hashtable<String, Boolean> modifiedItems = new Hashtable<String, Boolean>();

        System.out.println("TEST 1");
        System.out.println(modifiedItems.get("item1")); // Prints null
        System.out.println("TEST 2");
        System.out.println(modifiedItems.get("item1") == null); // Prints true
        System.out.println("TEST 3");
        System.out.println(Boolean.valueOf(null)); // Prints false
        System.out.println("TEST 4");
        System.out.println(Boolean.valueOf(modifiedItems.get("item1"))); // Produces NullPointerException
        System.out.println("FINISHED!"); // Never executed
    }
}

내 문제는 내가 왜 이해하지 못하는 것입니다 테스트 (3)가 잘 작동 (가 인쇄 false및 생산하지 않는 NullPointerException사이에) 시험 4 발생합니다 NullPointerException. 당신은 테스트에서 볼 수 있듯이 12 , null그리고 modifiedItems.get("item1")동등하고 있습니다 null.

동작은 Java 7 및 8에서 동일합니다.



답변

어떤 오버로드가 호출되는지주의 깊게 살펴 봐야합니다.

  • Boolean.valueOf(null)을 호출하고 Boolean.valueOf(String)있습니다. NPEnull 매개 변수가 제공된 경우에도 는 발생하지 않습니다 .
  • Boolean.valueOf(modifiedItems.get("item1"))호출되어 Boolean.valueOf(boolean)있기 때문에, modifiedItems의 값은 타입 인 Boolean개봉기 변환이 필요. 이후 modifiedItems.get("item1")이며 null, 그것은 그 값이다 개봉기 – 아닌 Boolean.valueOf(...)– NPE가 발생한다.

호출되는 오버로드를 결정하는 규칙은 매우 복잡 하지만 대략 다음과 같습니다.

  • 첫 번째 패스에서는 boxing / unboxing을 허용하지 않고 메서드 일치를 검색합니다 (변수 arity 메서드도 없음).

    • 왜냐하면 nullA에 대한 허용 값은 String아니지만 boolean, Boolean.valueOf(null)에 매칭 Boolean.valueOf(String)이 패스;
    • BooleanBoolean.valueOf(String)또는에 대해 허용되지 Boolean.valueOf(boolean)않으므로이 패스에서에 대해 일치하는 메서드가 없습니다 Boolean.valueOf(modifiedItems.get("item1")).
  • 두 번째 패스에서 메서드 일치를 검색하여 boxing / unboxing을 허용합니다 (하지만 여전히 가변 arity 메서드는 아님).

    • A는 Boolean로 박싱 될 수 boolean있으므로, Boolean.valueOf(boolean)에 대한 매칭 Boolean.valueOf(modifiedItems.get("item1"))이 패스; 그러나 unboxing 변환은 그것을 호출하기 위해 컴파일러에 의해 삽입되어야합니다 :Boolean.valueOf(modifiedItems.get("item1").booleanValue())
  • (가변 arity 메서드를 허용하는 세 번째 패스가 있지만 처음 두 패스가 이러한 경우와 일치하므로 여기서는 관련이 없습니다)


답변

이후 modifiedItems.get리턴한다 Boolean(이다 하지 스트 String)이며, 사용되는 서명 Boolean.valueOf(boolean)Boolean원시적으로 outboxed됩니다 boolean. 일단 null반환 되면 보낼 편지함이 NullPointerException.


답변

메서드 서명

이 메서드 Boolean.valueOf(...)에는 두 가지 서명이 있습니다.

  1. public static Boolean valueOf(boolean b)
  2. public static Boolean valueOf(String s)

귀하의 modifiedItems가치는 Boolean입니다. 당신은 캐스트 수 없습니다 BooleanString그래서 결과적으로 최초의 서명이 선택됩니다

부울 언 박싱

당신의 진술에서

Boolean.valueOf(modifiedItems.get("item1"))

다음과 같이 읽을 수 있습니다.

Boolean.valueOf(modifiedItems.get("item1").booleanValue())   

그러나 modifiedItems.get("item1")반환 null하므로 기본적으로

null.booleanValue()

분명히 NullPointerException


답변

Andy가 이미 그 이유를 잘 설명했듯이 NullPointerException:

이것은 Boolean un-boxing 때문입니다.

Boolean.valueOf(modifiedItems.get("item1"))

다음으로 변환됩니다.

Boolean.valueOf(modifiedItems.get("item1").booleanValue())

런타임 에 null이면 throw NullPointerException됩니다 modifiedItems.get("item1").

이제 여기에 다음 클래스를 각각의 프리미티브에 NullPointerExceptionunboxing하면 해당 반환 객체가 null 인 경우 예외가 발생할 수 있다는 점을 한 가지 더 추가하고 싶습니다 .

  1. 바이트-바이트
  2. char-문자
  3. float-부동
  4. int-정수
  5. 길다-길다
  6. 짧음-짧음
  7. double-더블

다음은 코드입니다.

    Hashtable<String, Boolean> modifiedItems1 = new Hashtable<String, Boolean>();
    System.out.println(Boolean.valueOf(modifiedItems1.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Byte> modifiedItems2 = new Hashtable<String, Byte>();
    System.out.println(Byte.valueOf(modifiedItems2.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Character> modifiedItems3 = new Hashtable<String, Character>();
    System.out.println(Character.valueOf(modifiedItems3.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Float> modifiedItems4 = new Hashtable<String, Float>();
    System.out.println(Float.valueOf(modifiedItems4.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Integer> modifiedItems5 = new Hashtable<String, Integer>();
    System.out.println(Integer.valueOf(modifiedItems5.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Long> modifiedItems6 = new Hashtable<String, Long>();
    System.out.println(Long.valueOf(modifiedItems6.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Short> modifiedItems7 = new Hashtable<String, Short>();
    System.out.println(Short.valueOf(modifiedItems7.get("item1")));//Exception in thread "main" java.lang.NullPointerException

    Hashtable<String, Double> modifiedItems8 = new Hashtable<String, Double>();
    System.out.println(Double.valueOf(modifiedItems8.get("item1")));//Exception in thread "main" java.lang.NullPointerException


답변

그것을 이해하는 방법은 언제 Boolean.valueOf(null)호출 되는지 , java는 정확하게 null을 평가하도록 지시받는 것입니다.

그러나 Boolean.valueOf(modifiedItems.get("item1"))가 호출되면 java는 객체 유형 Boolean의 HashTable에서 값을 가져 오도록 지시하지만 Boolean을 예상 했음에도 불구하고 대신 막 다른 골목 (null)을 찾는 Boolean 유형을 찾지 못합니다. NullPointerException 예외는 Java의이 부분의 작성자가이 상황이 프로그래머의주의를 요하는 프로그램에서 잘못되는 인스턴스라고 결정했기 때문에 발생합니다. (의도하지 않은 일이 발생했습니다.)

이 경우 의도적으로 null을 의도했다고 선언하는 것과 객체를 찾으려는 객체 (null)에 대한 누락 된 참조를 찾는 Java의 차이가 더 큽니다.

이 답변에서 NullPointerException에 대한 자세한 정보를 참조하십시오 :
https://stackoverflow.com/a/25721181/4425643


답변