Boolean.valueOf() produces NullPointerException sometimes
You've got to look carefully at which overload is being invoked:
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:
In a first pass, a method match is searched for without allowing boxing/unboxing (nor variable arity methods).
- 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"))
.
- Because
In a second pass, a method match is searched for, allowing boxing/unboxing (but still not variable arity methods).
- 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())
- A
(There's a third pass allowing for variable arity methods, but that's not relevant here, as the first two passes matched these cases)
Method signature
The method Boolean.valueOf(...)
has two signatures:
public static Boolean valueOf(boolean b)
public static Boolean valueOf(String s)
Your modifiedItems
value is Boolean
. You cannot cast Boolean
to String
so consequently the first signature will be chosen
Boolean unboxing
In your statement
Boolean.valueOf(modifiedItems.get("item1"))
which can be read as
Boolean.valueOf(modifiedItems.get("item1").booleanValue())
However, modifiedItems.get("item1")
returns null
so you'll basically have
null.booleanValue()
which obviously leads to a NullPointerException
Since modifiedItems.get
returns a Boolean
(which is not castable to a String
), the signature that would be used is Boolean.valueOf(boolean)
, where the Boolean
is outboxed to a primitive boolean
. Once null
is returned there, the outboxing fails with a NullPointerException
.