Boolean.valueOf() produces NullPointerException sometimes

后端 未结 5 1469
名媛妹妹
名媛妹妹 2021-01-30 08:14

I have this code:

package tests;

import java.util.Hashtable;

public class Tests {

    public static void main(String[] args) {

        Hashtable

        
相关标签:
5条回答
  • 2021-01-30 08:23

    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
    
    0 讨论(0)
  • 2021-01-30 08:24

    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.

    0 讨论(0)
  • 2021-01-30 08:27

    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)

    0 讨论(0)
  • 2021-01-30 08:33

    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

    0 讨论(0)
  • 2021-01-30 08:39

    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

    0 讨论(0)
提交回复
热议问题