请考虑以下代码段:
private static void doSomething(Double avg, Double min, Double sd) {
final Double testMin;
if (avg != null) {
testMin = Math.max(min, avg - 3 * sd);
} else {
testMin = min;
}
System.out.println("testMin=" + testMin);
final Double verwachtMin = avg != null ? Math.max(min, avg - 3 * sd) : min;
System.out.println("verwachtMin=" + verwachtMin);
}
据我所知(以及我的IDE可以告诉我的内容),变量testMin
和verwachtMin
应该是等效的。
正如您所料,我宁愿写下最后两行而不是第一行。但是,当我将3个空值传递给此方法时,我会计算verwachtMin
变量的NPE。
有谁知道这会怎么样?三元运算符是否评估第二部分,即使条件不是true
?
(Java版本1.6.0_21)
答案 0 :(得分:15)
尝试:
final Double verwachtMin = avg != null ? new Double(Math.max(min, avg - 3 * sd)) : min;
或
final Double verwachtMin = avg != null ? Double.valueOf(Math.max(min, avg - 3 * sd)) : min;
三元运算符的备用边的类型是double
和Double
,这意味着Double
被取消装箱到double
,然后在分配时我们有从double
到Double
的拳击。如果min
的值为null
,则取消装箱NPE。
答案 1 :(得分:3)
三元运算符是否评估第二部分,即使条件也是如此 不是真的
否 - 但它会评估第3部分,我认为在这种情况下它会尝试自动加载min
(导致NPE),因为Math.max()
的返回类型是原始的double
和确定整个表达式的返回类型。
Autoboxing / -unboxing是魔鬼。
答案 2 :(得分:1)
问题是由autoboxing *引起的,而不是由三元运算符引起的。您正在使用Double
包装器类型而不是double
基元类型。由于Math.max()
需要double
参数,而不是Double
s,因此在将值传递给Math.max()
之前,会对Double#doubleValue()
进行不可见的调用。但是,您无法在null
对象上调用方法 - 因此NullPointerException
。
为什么您首先使用Double
而不是double
?原始类型变量(例如double
)根本不能是null
。
*嗯,autounboxing,在这种情况下
答案 3 :(得分:0)
自动取消装箱会导致问题。之前已经问过类似的问题..你应该使用double而不是Double来解决你的问题..
答案 4 :(得分:0)
Math.max(min, avg - 3 * sd)
此处min
,avg
和sd
自动从Double到double,当其中一个为null时会导致NPE。