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行aNullPointerException。正如你在tests1and2,nullmodifiedItems.get("item1")中看到的那样等于和null

Java 7和8中的行为是相同的。


#1 热门回答(167 赞)

你必须仔细查看正在调用的重载:

  • Boolean.valueOf(null)正在调用Boolean.valueOf(String)。即使提供了null参数,也不会抛出NPE。
  • Boolean.valueOf(modifiedItems.get("item1"))正在调用Boolean.valueOf(boolean),因为modifiedItems的值是Boolean类型,需要进行拆箱转换。由于modifiedItems.get("item1")为null,因此它是该值的拆箱 - 而不是Boolean.valueOf(...) - 它会抛出NPE。

确定调用哪个重载的规则是pretty hairy,但它们大致如下:

  • 在第一遍中,搜索方法匹配而不允许装箱/拆箱(也不是变量arity方法)。因为null是String的可接受值而不是boolean,所以Boolean.valueOf(null)在此传递中与Boolean.valueOf(String)匹配;布尔值对于Boolean.valueOf(String)或Boolean.valueOf(boolean)是不可接受的,因此对于Boolean.valueOf(modifiedItems.get("item1")),此传递中没有匹配任何方法。
  • 在第二遍中,搜索方法匹配,允许装箱/拆箱(但仍然不是可变的arity方法)。布尔值可以取消装箱为布尔值,因此在此过程中布尔值(布尔值)布尔值与布尔值相同(modifiedItems.get("item1"));但是编译器必须插入一个取消装箱转换才能调用它:Boolean.valueOf(modifiedItems.get("item1")。booleanValue())
  • (第三次传递允许变量arity方法,但这里没有相关性,因为前两次传递匹配这些情况)

#2 热门回答(13 赞)

由于modifiedItems.get返回aBoolean(即而不是castable至aString),将使用的签名是Boolean.valueOf(boolean),其中Boolean的外包为原始boolean。 Oncenull返回那里,发件箱失败,aNullPointerException


#3 热门回答(11 赞)

##方法签名

方法Boolean.valueOf(...)有两个签名:

  • public static Boolean valueOf(boolean b)
  • public static Boolean valueOf(String s)

YourmodifiedItemsvalue是Boolean。你不能投射BooleanString,因此将选择第一个签名

Boolean取消装箱

在你的陈述中

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

可以读作

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

但是,modifiedItems.get("item1")returnsnull你基本上都有

null.booleanValue()

这显然导致aNullPointerException