如果像例子那样,我正在使用三元:
carDto.setTireId(car.getTire() == null ? null : car.getTire().getId());
导致NullPointer异常。我不明白为什么,但后来我注意到setTireId期望整数作为参数。所以当我改为
时carDto.setTireId(car.getTire() == null ? 0 : car.getTire().getId());
一切都按预期开始了。
当我尝试
时carDto.setTireId(null);
我按预期得到了编译异常。
我的问题是:为什么第一个语句在编译时没有失败?在这种情况下,这是一个简单的人为错误,但它可能会造成一个难以发现的错误。
答案 0 :(得分:-1)
因为为了使语句在编译时失败,编译器必须解决?的逻辑?运算符在编译时,看到null进入setTireId。逻辑?只在运行时解决,所以编译器很幸福地没有意识到null进入需要int的函数。
让我看看我是否可以为你完成Java specs的逻辑: 在编译类型,因为类型不同,装箱转换应用于null,但这只是一个回复null的标识转换。拳击转换也适用于int,给予Int。根据规范,规则是如果你有null和引用类型,那么结果的类型是引用类型,即Int。编译器此时无法评估运算符的逻辑,这是问题的症结所在,因此它有两个自动装箱到Int的操作数,它假定你的setTireId将接受一个Int类型,继续前进。 字符串不会发生相同的链,因为如果两者中的一个的类型是字符串而另一个是引用类型,则没有规定会发生什么,就像null和引用类型一样。
在运行时,null被计算为null Int,但是您的函数不能接受null Int,因此您会收到运行时错误。更具体地说,当结果是?是一个null Int,运行时尝试取消装置以获取函数所需的int,但是取消装入null会产生空指针异常,因此会出现运行时错误。
这种理解不正确吗?