Java NPE 在三元运算符与自动装箱?

2022-09-02 03:02:40

今天早上,我遇到了一个非常奇怪的NPE,并将其简化为一个简单的例子。这是 JVM 错误还是正确的行为?

public class Test1 {
    class Item {
        Integer id = null;
        public Integer getId() {return id;}
    }   
    public Integer f() {
        Item item = new Item();
        // this works:
        //return item == null ? new Integer(1) : item.getId();

        // NPE??
        return item == null ? 1 : item.getId();
    }   
    public static void main(String[] args) {
        Test1 t = new Test1();
        System.out.println("id is: " + String.valueOf(t.f()));
    }   
}

编译和运行的输出:

$ javac Test1.java 
$ java Test1
Exception in thread "main" java.lang.NullPointerException
at Test1.f(Test1.java:12)
at Test1.main(Test1.java:16)
$

答案 1

表达式的类型不是 。因此,Java 需要自动将 您 拆箱到 一个 (导致 )。然后,它将结果自动框回 a(如果不是 ),则从该方法返回。item == null ? 1 : item.getId()intIntegerIntegerintNullPointerExceptionIntegerNullPointerException

另一方面,表达式具有一种类型,并且不需要执行自动取消装箱。item == null ? new Integer(1) : item.getId()Integer

当您自动取消装箱 a 时,您将获得一个(请参阅自动装箱),这就是您正在经历的情况。nullIntegerNullPointerException

要回答您的问题,这是正确的行为。


答案 2

如果反编译类文件,您将清楚地看到您的 NPE...

return Integer.valueOf(item != null ? item.getId().intValue() : 1);

推荐