You’ve got to look carefully at which overload is being invoked:
Boolean.valueOf(null)is invokingBoolean.valueOf(String). This doesn’t throw anNPEeven 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
nullis an acceptable value for aStringbut notboolean,Boolean.valueOf(null)is matched toBoolean.valueOf(String)in this pass; Booleanisn’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
Booleancan 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)