三元运算符中不需要的 NullPointerException - 为啥? [复制]
Posted
技术标签:
【中文标题】三元运算符中不需要的 NullPointerException - 为啥? [复制]【英文标题】:Unwanted NullPointerException in ternary operator - Why? [duplicate]三元运算符中不需要的 NullPointerException - 为什么? [复制] 【发布时间】:2019-02-08 08:42:48 【问题描述】:在执行以下代码时,我在行收到NullPointerException
:
value = condition ? getDouble() : 1.0;
在前面几行中,当我使用 null
而不是 getDouble()
时,一切正常,这很奇怪。
public class Test
static Double getDouble()
return null;
public static void main(String[] args)
boolean condition = true;
Double value;
value = condition ? null : 1.0; //works fine
System.out.println(value); //prints null
value = condition ? getDouble() : 1.0; //throws NPE
System.out.println(value);
谁能帮我理解这种行为?
【问题讨论】:
“将 getDouble() 更改为 null”是什么意思?该方法已在您发布的代码中返回 null。 这很奇怪...如果我更改为 null 一切正常。虽然方法返回 null 当我说更改为 null 意味着......而不是调用返回 null 的方法时,我直接使用了 null 可能相关:Tricky ternary operator in Java - autoboxing 我试图简化并同时澄清您的示例。如果我误解了您的意图,请随时回滚我的编辑。 【参考方案1】:当你写作时
value = condition ? null : 1.0;
condition ? null : 1.0
的类型必须是引用类型,所以类型为Double
,可以持有值null
。
当你写作时
value = condition ? getDouble() : 1.0;
而getDouble()
返回null
,相当于写:
value = condition ? ((Double) null) : 1.0;
在这种情况下,编译器将Double
和double
视为三元条件运算符的第二个和第三个参数,并决定表达式的类型应为double
。因此,它将null
拆箱为double
,得到NullPointerException
。
条件三元运算符的类型由JLS 15.25中的一些表决定。
如果第二个和第三个操作数是null
和double
,则条件表达式类型是Double
和null
的最小上界,即Double
。
如果第二和第三个操作数是Double
和double
,则条件表达式类型是double
。
【讨论】:
很奇怪。我会为此提出某种票证。即使语言标准说编译器应该选择double
,这是一个缩小转换,因为double
不支持null
。如果我没记错的话,所有其他隐式缩小转换都像瘟疫一样被避免。我应该认为应该改变它以保持一致性。
根据上面的答案...您可以将其更改为以下内容,它将正常工作value = condition ? getDouble() : new Double(1.0);
为什么会有人知道?【参考方案2】:
见#jls-15.25:
如果第二个操作数是Double
,而第三个操作数是double
,则结果:
getCount() == 1 ? getDouble() : 1.0
将是double
。
当您尝试将Double null
(由getDouble()
返回)转换为double
时,将抛出NPE
。
【讨论】:
在 JLS 上更进一步:15.25.2 说:“如果第二个和第三个操作数之一是原始类型T
,而另一个的类型是对 @ 应用装箱转换的结果987654333@,则条件表达式的类型为T
。"拳击因 NPE 失败。以上是关于三元运算符中不需要的 NullPointerException - 为啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章