nullpointerexception Java:如何避免三元运算符中的NPE,通常如何优雅地执行nullchecks?
昨天我不得不编写一段难看的代码,以便对对象的字段执行许多空检查,以避免三元运算符构造的NPE
有问题的代码:
ResourceThresholds rt = getThresholdsFromConfig();
Thresholds defaultPerContainer = getDefaultThresholds();
return new Thresholds((!rt.getCpu().equals("")) ? Long.parseLong(rt.getCpu()) : defaultPerContainer.getCpu(),
(!rt.getMemory().equals("")) ? Long.parseLong(rt.getMemory()) : defaultPerContainer.getMemory(),/*omitted for brevity*/);
我在defaultPerContainer.getCpu()
上得到一个NPE,因为字段cpu = null
。
这很好,Java就是这样工作的。
为什么我没有默认设置字段Long cpu = 0L;
?因为我需要null
值作为我们不设置任何值的指示符
这段特定代码的最终功能变体是:
Long cpuVal;
if (!rt.getCpu().equals("")) {
cpuVal = Long.parseLong(rt.getCpu());
} else {
cpuVal = defaultPerContainer.getCpu();
}
Long memory;
if (!rt.getMemory().equals("")) {
memory = Long.parseLong(rt.getMemory());
} else {
memory = defaultPerContainer.getMemory();
}
//... many similar if-elses that give me the desired value;
//which is really ugly, and I believe I am not the only one hitting this.
return new Thresholds(cpuVal, memory..);
这段代码按照我需要的方式工作,但它很难看
问题1:有人能告诉我,我是否能找到一种方法,使用Optional<T>
用三元运算符解析第一个变量中的NPE?因为这个代码段是有效的:!rt.getCpu().equals("")) ? Long.parseLong(rt.getCpu()) : null
也就是说,如果我显式地把null
作为一个值,当条件满足时,我会得到null
一般来说,有什么优雅的Java8+方法可以解决这个问题吗
问题2:如何优化用于空检查的if-else构造
# 1 楼答案
问题是,在三元表达式
A ? B : C
中,如果B
和C
都是兼容的数字类型,但一个是装箱对象,另一个是原语,大多数人会认为通过自动装箱原语,结果是装箱的事实并非如此。三元运算符会取消对象的绑定,因此它们都是基元,结果就是基元
这意味着以下内容是相同的:
结果是,如果
C
为空,则得到NPE解决这个问题的一种方法是强制
B
自动装箱:通过这种更改,空的
C
值只需设置R = null
在问题中的例子中,}
B
是Long.parseLong(rt.getCpu())
,因此与其添加强制自动装箱的强制转换,不如使用^{另外,不相关的,用
isEmpty()
代替equals("")
,并且A
周围不需要括号将代码更改为:
# 2 楼答案
null
检查李>cpu
和memory
时使用它,如果val
是null
,则使用Joda条件"".equals(val)
来防止NPELong.valueOf
而不是返回原语long
的Long.parseLong
:还可以使用参数提供者提供重载实用程序方法,然后将方法引用传递给它: