Boolean.valueOf() produces NullPointerException sometimes

12,147

Solution 1

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).

    • Because 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).

    • A 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)

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:

  1. public static Boolean valueOf(boolean b)
  2. 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.

  1. byte - Byte
  2. char - Character
  3. float - Float
  4. int - Integer
  5. long - Long
  6. short - Short
  7. 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
Share:
12,147

Related videos on Youtube

David E
Author by

David E

Updated on June 08, 2022

Comments

  • David E
    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 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.

    The behavior is the same in Java 7 and 8.

    • Stultuske
      Stultuske over 6 years
      modifiedItems.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
      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
      candied_orange over 6 years
      I'm impressed. This is the most interesting null pointer exception question I've seen in years.
    • Andy Turner
      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
    Al-un over 6 years
    Incorrect 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
    Andy Turner over 6 years
    Don't delete it on my account. Remember, this isn't a zero-sum game: people can (and do) upvote multiple answers.
  • Andy Turner
    Andy Turner over 6 years
    "Converted into ... at runtime" it's converted to that at compile time.
  • CausingUnderflowsEverywhere
    CausingUnderflowsEverywhere over 6 years
    If 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
    CausingUnderflowsEverywhere over 6 years
    Could code be more clear if we use Boolean.valueOf(modifiedItems.get("item1").booleanValue()) in source code instead of Boolean.valueOf(modifiedItems.get("item1")) ?
  • Andy Turner
    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
    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.