Why does a ternary conditional expression returning null and assigned to a reference type cause a NullPointerException? [duplicate]

我怕爱的太早我们不能终老 提交于 2019-12-17 13:49:13

问题


I like to use the ternary conditional expression in java programming, but I experienced an issue :

The following code is a small example, but it shows the problem that I have found.

public class Example {

    public Example() {
        Double x = 0.0;    
        A a = new A();   
        x = a == null ? 0.0 : a.getY();   // Happens on this line    
        System.out.println(x);
    }

    class A {
        Double y = null;  
        private Double getY() {
            return y;
        }
    }

    public static void main(String[] args) {
        new Example();
    }

}

What's causing the NullPointerException?


回答1:


This results from the JLS rules of determining the type of the ternary conditional expression :

If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

This rule means that the type of the ternary expression is double and not Double. Unboxing the Double returned by your a.getY() method to double causes NullPointerException, since that method returns null.

a == null ? 0.0   : a.getY();
            double   Double      -> hence the type of the ternary expression is double



回答2:


It happens because 0.0 is of type double, not Double. The second two operands to the conditional operator must be of the same type, so autoboxing/unboxing came into it and the compiler turned that code into:

x = Double.valueOf(a == null ? 0.0 : a.getY().doubleValue());
// -^^^^^^^^^^^^^^^--------------------------^^^^^^^^^^^^^^

...which throws because a.getY() returns null, and then the code tries to call doubleValue on null.

If we run javap -c Example to decompile the code, we can see those calls (I've put them in bold):

public class Example {
  public Example();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: dconst_0
       5: invokestatic  #2                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
       8: astore_1
       9: new           #3                  // class Example$A
      12: dup
      13: aload_0
      14: invokespecial #4                  // Method Example$A."":(LExample;)V
      17: astore_2
      18: aload_2
      19: ifnonnull     26
      22: dconst_0
      23: goto          33
      26: aload_2
      27: invokestatic  #5                  // Method Example$A.access$000:(LExample$A;)Ljava/lang/Double;
      30: invokevirtual #6                  // Method java/lang/Double.doubleValue:()D
      33: invokestatic  #2                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      36: astore_1
      37: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      40: aload_1
      41: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      44: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #9                  // class Example
       3: dup
       4: invokespecial #10                 // Method "":()V
       7: pop
       8: return
}


来源:https://stackoverflow.com/questions/37984033/why-does-a-ternary-conditional-expression-returning-null-and-assigned-to-a-refer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!