Boolean.valueOf()有时会生成NullPointerException

时间:2017-10-06 08:04:41

标签: java nullpointerexception boolean

我有这段代码:

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
    }
}

我的问题是我不明白为什么 Test 3 工作正常(打印false并且不会产生NullPointerException)同时测试4 抛出NullPointerException。正如您在测试 1 2 中看到的那样,nullmodifiedItems.get("item1")等于null

Java 7和8中的行为相同。

5 个答案:

答案 0 :(得分:170)

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

  • 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方法)。

    • 由于nullString但不是boolean的可接受值,Boolean.valueOf(null)在此次传递中与Boolean.valueOf(String)匹配;
    • Boolean对于Boolean.valueOf(String)Boolean.valueOf(boolean)来说是不可接受的,因此Boolean.valueOf(modifiedItems.get("item1"))的传递中没有匹配任何方法。
  • 在第二遍中,搜索方法匹配,允许装箱/拆箱(但仍然不是可变的arity方法)。

    • Boolean可以取消装箱到boolean,因此Boolean.valueOf(boolean)在此通行证中与Boolean.valueOf(modifiedItems.get("item1"))匹配;但是编译器必须插入一个取消装箱的转换才能调用它:Boolean.valueOf(modifiedItems.get("item1").booleanValue())
  • (允许使用变量arity方法的第三次传递,但这里没有相关性,因为前两次传递符合这些情况)

答案 1 :(得分:13)

由于modifiedItems.get会返回Boolean可投递到String),因此将使用的签名为Boolean.valueOf(boolean),将Boolean外包到原始boolean的位置。在此处返回null后,发件箱将失败并显示NullPointerException

答案 2 :(得分:11)

方法签名

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

  1. public static Boolean valueOf(boolean b)
  2. public static Boolean valueOf(String s)
  3. 您的modifiedItems值为Boolean。您无法将Boolean转换为String,因此将选择第一个签名

    布尔取消装箱

    在你的陈述中

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

    可以读作

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

    但是,modifiedItems.get("item1")会返回null,因此您基本上会有

    null.booleanValue()
    

    显然会导致NullPointerException

答案 3 :(得分:4)

Andy已经很好地描述了NullPointerException

的原因

这是由于布尔解除拳击:

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

转换为:

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

在运行时,如果NullPointerException为空,则抛出modifiedItems.get("item1")

现在我想在此处再补充一点,即如果相应的返回对象为空,则将以下类拆分为各自的基元也会产生NullPointerException异常。

  1. byte - Byte
  2. char - Character
  3. float - Float
  4. int - Integer
  5. long - Long
  6. 短 - 短
  7. double - Double
  8. 以下是代码:

        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
    

答案 4 :(得分:1)

理解它的一种方法是在调用Boolean.valueOf(null)时,精确地告诉java评估null。

但是,当调用Boolean.valueOf(modifiedItems.get("item1"))时,java会被告知从对象类型为布尔值的HashTable中获取一个值,但它找不到布尔类型,而是找到一个死胡同(null),即使它预期布尔值。引发NullPointerException异常是因为java的这一部分的创建者决定这种情况是程序出错的某个实例需要程序员的注意。 (发生了意想不到的事情。)

在这种情况下,更有意义的是故意声明你打算将null放在那里,而java找到一个对象(null)的缺失引用,其中找到一个对象。

在此答案中查看有关NullPointerException的更多信息: https://stackoverflow.com/a/25721181/4425643