我有这段代码:
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 中看到的那样,null
和modifiedItems.get("item1")
等于null
。
Java 7和8中的行为相同。
答案 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方法)。
null
是String
但不是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(...)
有两个签名:
public static Boolean valueOf(boolean b)
public static Boolean valueOf(String s)
您的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
异常。
以下是代码:
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