I have this code:
package tests;
import java.util.Hashtable;
public class Tests {
public static void main(String[] args) {
Hashtable
As Andy already very well described the reason of NullPointerException
:
which is due to Boolean un-boxing:
Boolean.valueOf(modifiedItems.get("item1"))
get converted into:
Boolean.valueOf(modifiedItems.get("item1").booleanValue())
at runtime and then it throw NullPointerException
if modifiedItems.get("item1")
is null.
Now I would like to add one more point here that un-boxing of the following classes to their respective primitives can also produce NullPointerException
exception if their corresponding returned objects are null.
Here is the code:
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
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
.
You've got to look carefully at which overload is being invoked:
Boolean.valueOf(null)
is invoking Boolean.valueOf(String). This doesn't throw an NPE
even if supplied with a null parameter.Boolean.valueOf(modifiedItems.get("item1"))
is invoking Boolean.valueOf(boolean), because modifiedItems
's values are of type Boolean
, which requires an unboxing conversion. Since modifiedItems.get("item1")
is null
, it is the unboxing of that value - not the Boolean.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).
null
is an acceptable value for a String
but not boolean
, Boolean.valueOf(null)
is matched to Boolean.valueOf(String)
in this pass;Boolean
isn't an acceptable for either Boolean.valueOf(String)
or Boolean.valueOf(boolean)
, so no method is matched in this pass for Boolean.valueOf(modifiedItems.get("item1"))
.In a second pass, a method match is searched for, allowing boxing/unboxing (but still not variable arity methods).
Boolean
can be unboxed to boolean
, so Boolean.valueOf(boolean)
is matched for Boolean.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)
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
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
A way to understand it is when Boolean.valueOf(null)
is invoked, java is precisely being told to evaluate null.
However, when Boolean.valueOf(modifiedItems.get("item1"))
is invoked, java is told to obtain a value from the HashTable of object type Boolean, but it doesn't find the type Boolean it finds a dead end instead (null) even though it expected Boolean. The NullPointerException exception is thrown because the creators of this part of java decided this situation is an instance of something in the program going wrong that needs the programmer's attention. (Something unintended happened.)
In this case it is more the difference between deliberately declaring that you intended the null to be there, and java finding a missing reference to an object (null) where an object was intended to be found.
See more information about NullPointerException in this answer: https://stackoverflow.com/a/25721181/4425643