我最近通过随机临时测试在我的代码中发现了一个不寻常的错误。所以,我为它做了一个测试用例。
这是我的测试用例:
SampleRequest request = new SampleRequest();
request.setA(null);
request.setB(null);
assertEquals(null, request.getAOrB());
A 和 B 被定义为 java.lang.Integer 类型并具有直接的 setter 方法来将它们的值设置到请求中。
还涉及到枚举。它有一个原始整数值,以及此代码中使用的方法。我将在这里发布相关部分:
enum Swapper {
public int c;
Swapper findSwapperToUse(final int a) {
for(Swapper swapper : values()) {
if(swapper.c == a) {
return swapper;
}
}
return null;
}
}
现在,这是令人困惑的方法。在该方法上调用测试方法会导致 NPE,但在方法的最后一行。
public class SampleRequest {
private Integer A;
private Integer B;
public void setA(final Integer A) {
this.A = A;
}
public void setB(final Integer B) {
this.B = B;
}
public Integer getAOrB() {
return A != null ? Swapper.findSwapperToUse(A).c
: B;
}
}
在测试中,A 和 B 都设置为空。因此,A != null 返回 false。但是,我在 : B 行的行号处收到 NullPointerException。
我的猜测是,由于某种原因,正在评估第一个表达式 Swapper.findSwapperToUse(A).c,因此 A.intValue() 通过自动装箱调用,导致空值出现 NullPointerException。通过调试得知 findSwapperToUse() 没有被调用。
但是,根据这个问题,这不应该发生: Java ternary (immediate if) evaluation
未选择的操作数表达式不会针对条件表达式的特定评估进行评估。
返回 null (B) 不会导致 NullPointerException - 在这里返回 null 结果是完全可以的。
到底他妈发生了什么?
编辑:我忘了补充一点,我通过使用直接的 if 语句更改了代码以避免这种情况 - 以下代码确实按预期工作:
public Integer getAOrB() {
if(A != null) {
return Swapper.findSwapperToUse(A).c;
}
return B;
}