Boolean.valueOf() 有时会产生 NullPointerException [英] Boolean.valueOf() produces NullPointerException sometimes
问题描述
我有这个代码:
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
.
My problem is that I don't understand why Test 3 works fine (it prints false
and doesn't produce NullPointerException
) meanwhile Test 4 throws a NullPointerException
. As you can see in tests 1 and 2, null
and modifiedItems.get("item1")
are equals and null
.
Java 7 和 8 中的行为相同.
The behavior is the same in Java 7 and 8.
推荐答案
您必须仔细查看正在调用的重载:
You've got to look carefully at which overload is being invoked:
Boolean.valueOf(null)
正在调用Boolean.valueOf(String)
.即使提供了空参数,这也不会抛出NPE
.Boolean.valueOf(modifiedItems.get("item1"))
正在调用Boolean.valueOf(boolean)
,因为modifiedItems
的值是类型Boolean
,需要进行拆箱转换.由于modifiedItems.get("item1")
是null
,它是该值的拆箱 - 而不是Boolean.valueOf(...)
- 抛出 NPE.
Boolean.valueOf(null)
is invokingBoolean.valueOf(String)
. This doesn't throw anNPE
even if supplied with a null parameter.Boolean.valueOf(modifiedItems.get("item1"))
is invokingBoolean.valueOf(boolean)
, becausemodifiedItems
's values are of typeBoolean
, which requires an unboxing conversion. SincemodifiedItems.get("item1")
isnull
, it is the unboxing of that value - not theBoolean.valueOf(...)
- which throws the NPE.
确定调用哪个重载的规则是相当多毛,但它们大致是这样的:
The rules for determining which overload is invoked are pretty hairy, but they roughly go like this:
在第一遍中,在不允许装箱/拆箱(也不允许变量arity方法)的情况下搜索方法匹配.
In a first pass, a method match is searched for without allowing boxing/unboxing (nor variable arity methods).
- 因为
null
是String
但不是boolean
的可接受值,所以Boolean.valueOf(null)
在这个pass中匹配到Boolean.valueOf(String)
; Boolean
对Boolean.valueOf(String)
或Boolean.valueOf(boolean)
都是不可接受的,所以没有方法是在此传递中匹配Boolean.valueOf(modifiedItems.get("item1"))
.
- Because
null
is an acceptable value for aString
but notboolean
,Boolean.valueOf(null)
is matched toBoolean.valueOf(String)
in this pass; Boolean
isn't an acceptable for eitherBoolean.valueOf(String)
orBoolean.valueOf(boolean)
, so no method is matched in this pass forBoolean.valueOf(modifiedItems.get("item1"))
.
在第二遍中,搜索方法匹配,允许装箱/拆箱(但仍然不是可变数量方法).
In a second pass, a method match is searched for, allowing boxing/unboxing (but still not variable arity methods).
Boolean
可以拆箱为boolean
,所以Boolean.valueOf(boolean)
与Boolean.valueOf(modifiedItems.get("item1"))
在这个pass中;但是编译器必须插入一个拆箱转换来调用它:Boolean.valueOf(modifiedItems.get("item1").booleanValue())
- A
Boolean
can be unboxed toboolean
, soBoolean.valueOf(boolean)
is matched forBoolean.valueOf(modifiedItems.get("item1"))
in this pass; but an unboxing conversion has to be inserted by the compiler to invoke it:Boolean.valueOf(modifiedItems.get("item1").booleanValue())
(第三遍允许可变数量方法,但这与此处无关,因为前两遍与这些情况匹配)
(There's a third pass allowing for variable arity methods, but that's not relevant here, as the first two passes matched these cases)
这篇关于Boolean.valueOf() 有时会产生 NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!