Boolean.valueOf() produces NullPointerException sometimes
Solution 1
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)
Solution 2
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
.
Solution 3
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
Solution 4
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.
- byte - Byte
- char - Character
- float - Float
- int - Integer
- long - Long
- short - Short
- double - Double
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
Related videos on Youtube
David E
Updated on June 08, 2022Comments
-
David E about 2 years
I have this code:
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 } }
My problem is that I don't understand why Test 3 works fine (it prints
false
and doesn't produceNullPointerException
) meanwhile Test 4 throws aNullPointerException
. As you can see in tests 1 and 2,null
andmodifiedItems.get("item1")
are equals andnull
.The behavior is the same in Java 7 and 8.
-
Stultuske over 6 yearsmodifiedItems.get("item1") this is null, you are aware of that, but you assume that passing this to a valueOf will not end up in a NPE?
-
psmears over 6 years@Stultuske: It's a valid question, given that just two lines above passing a literal
null
to the same function doesn't generate an NPE! There's a good reason for it, but it's certainly confusing at first sight :-) -
candied_orange over 6 yearsI'm impressed. This is the most interesting null pointer exception question I've seen in years.
-
Andy Turner over 6 years@Jeroen this isn't a dupe of that question. Whilst it is true that unboxing is common to the two problems, there is no comparison going on here. The key thing about this question is that it occurs because of the way overloads are resolved; and that's quite a different thing from how
==
is applied.
-
-
Al-un over 6 yearsIncorrect wording, thanks for pointing and answer is updated following your feedback. Apologies, I haven't seen your answer while writing and I see that mine looks like yours. Should I remove my answer to avoid confusion for OP?
-
Andy Turner over 6 yearsDon't delete it on my account. Remember, this isn't a zero-sum game: people can (and do) upvote multiple answers.
-
Andy Turner over 6 years"Converted into ... at runtime" it's converted to that at compile time.
-
CausingUnderflowsEverywhere over 6 yearsIf someone can help improve this answer, I was thinking of a word that refers to the programmer writing something with clear intention, with no ambiguity
-
CausingUnderflowsEverywhere over 6 yearsCould code be more clear if we use
Boolean.valueOf(modifiedItems.get("item1").booleanValue())
in source code instead ofBoolean.valueOf(modifiedItems.get("item1"))
? -
Andy Turner over 6 years@CausingUnderflowsEverywhere not really - it is really hard to see that
.booleanValue()
buried in the expression. Two observations: 1) auto(un)boxing is a deliberate feature of Java to remove syntactic cruft; doing it yourself is possible, but not idiomatic; 2) this doesn't help you at all - it certainly doesn't stop the problem from occurring, nor does it give any extra info when the failure does occur (the stack trace would be identical, because the executed code is identical). -
Andy Turner over 6 years@CausingUnderflowsEverywhere it is better to use tooling to highlight the issues, e.g. intellij would earn you about potential NPE here.