java - 在 Java 的三元运算符中,即使表达式结果为假值,是否可以计算第一个参数?

标签 java ternary-operator

我最近通过随机临时测试在我的代码中发现了一个不寻常的错误。所以,我为它做了一个测试用例。

这是我的测试用例:

 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都设置为null。因此,A != null 返回 false。但是,我在 : B 行的行号处收到 NullPointerException。

我的猜测是,出于某种原因,第一个表达式 Swapper.findSwapperToUse(A).c 正在被评估,因此 A.intValue() 是通过自动装箱调用的,导致空值出现 NullPointerException。通过调试得知findSwapperToUse()没有被调用。

然而,根据这个问题,这不应该发生: Java ternary (immediate if) evaluation

The operand expression not chosen is not evaluated for that particular evaluation of the conditional expression.

返回 null (B) 不会导致 NullPointerException - 在这里返回 null 结果完全没问题。

这到底是怎么回事?

编辑:我忘了补充一点,我通过使用直接的 if 语句更改了代码以避免这种情况 - 以下代码确实按预期工作:

public Integer getAOrB() {
    if(A != null) {
        return Swapper.findSwapperToUse(A).c;
    }
    return B;
}

最佳答案

我猜这个问题是由编译器推断整个表达式的类型引起的

A != null ? Swapper.findSwapperToUse(A).c : B

作为 Swapper.c 类型的 int,因此尝试将拆箱转换应用于 B

这是来自 the JLS, §15.25 的相关摘录:

  • Otherwise, if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases:
    • ...
    • Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands. Note that binary numeric promotion performs unboxing conversion (§5.1.8) and value set conversion (§5.1.13).

您可以通过添加以下强制转换来阻止它:

A != null ? (Integer) Swapper.findSwapperToUse(A).c : B

关于java - 在 Java 的三元运算符中,即使表达式结果为假值,是否可以计算第一个参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4923659/

相关文章:

java - 由于语法错误表未在数据库中创建

c# - 右侧的三元/空合并运算符和赋值表达式?

ruby - 有人可以向我解释以下代码吗?

javascript - JSX 三元表达式对于 Map 的行为不同

javascript - 仅当条件在 JavaScript 中的三元运算符中为真时才赋值

java - 如何在 Java 中使用 ObjectInputStream 读取不同的对象

java - 如何记录我的项目上的 Activity

java - 如何将一个数组列表深度复制到另一个数组列表中

javascript - 三元运算符内的赋值,反模式?

java - 修剪 OpenCSV 中的前导和尾随空格