Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带自动装箱的三元运算符中的Java NPE?_Java_Nullpointerexception - Fatal编程技术网

带自动装箱的三元运算符中的Java NPE?

带自动装箱的三元运算符中的Java NPE?,java,nullpointerexception,Java,Nullpointerexception,今天早上我遇到了一个非常奇怪的NPE,并将其简化为一个简单的示例。这是JVM错误还是正确的行为 public class Test1 { class Item { Integer id = null; public Integer getId() {return id;} } public Integer f() { Item item = new Item(); // this works:

今天早上我遇到了一个非常奇怪的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)
$

item
可能不是
null
,但是当您调用
getId()
时,它将返回
null
。当您尝试自动取消装箱
null
时,您会得到一个NPE。

下面的返回类型是
整数
-

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

    // NPE??
    return item == null ? 1 : item.getId();
}
下面的结果是什么-

item == null ? 1 : item.getId()
在您的情况下为
null

因此,JVM抛出NPE是因为它试图自动装箱
null

试一试-


两者都将抛出NPE。

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

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

表达式
item==null的类型?1:item.getId()
int
不是
Integer
。因此,Java需要将您的
整数
自动取消装箱为
int
(导致
NullPointerException
)。然后,它会自动将结果返回到一个
整数
(如果不是
NullPointerException
),从该方法返回

另一方面,表达式
item==null?新整数(1):item.getId()的类型为
Integer
,无需自动取消装箱

当您自动取消对
null
Integer
的装箱时,您会得到一个
NullPointerException
(请参阅),这就是您遇到的情况


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

之所以发生这种情况,是因为您使用的是条件运算符
。线

返回项==null?1:item.getId()

相当于

int result = item == null ? 1 : item.getId();
return result;
由于表达式中的第一个操作数,结果为int。这就是当您显式地用整数包装1时代码工作的原因。在本例中,编译器创建如下内容

Integer result = item == null ? new Integer(1) : item.getId();
return result;

因此,NPE在尝试将item.getId()(即null)强制转换为int时发生。

pst使用
Integer.valueOf(1)
而不是
newinteger(1)
,这是自动装箱的好方法。这就是为什么流行的最佳实践建议在包装器上使用基本类型。非常类似于您确定吗?getId返回一个正好为null的整数,因此不应该有自动装箱。如果你说的是真的,那么为什么返回
新整数(1)
会使NPE消失呢?@Kevin使用
新整数(1)
,第二个和第三个操作数都是
整数
类型,所以这就是条件类型。对于
1
,条件表达式的类型是
int
,因此
getId()
的返回值被取消绑定为
int
。(查看JLS的第15.25节,了解关于这方面的确切规则。)
Integer result = item == null ? new Integer(1) : item.getId();
return result;