为什么在对同一个getter调用两次时,三元运算符的行为会不同?

前端开发 2026-07-12

我在研究Java在方法调用涉及时对三元运算符的求值行为。

看下面这个简化的示例:

class SampleDto {

    private Integer number;

    public Integer getNumber() {
        System.out.println("getNumber() invoked");
        return number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }
}

用法:

SampleDto dto = new SampleDto();
dto.setNumber(42);

Integer result =
        dto.getNumber() != null
                ? dto.getNumber()
                : 100;

System.out.println("Result = " + result);

输出:

getNumber() invoked
getNumber() invoked
Result = 42

因此getter方法会被调用两次。

在我的实际项目中,getter并非一个简单的字段访问器——它内部包含逻辑,且可能依赖可变状态。把它放在这样的三元表达式中会导致结果不一致。

我的问题:

  1. Java语言规范是否保证条件表达式和所选分支表达式会分别独立求值?
  2. Java是否会进行任何优化以避免重复的方法调用?
  3. 当方法不是纯访问器时,将方法结果存储在局部变量中是否被认为是最佳实践?

例如:

Integer value = dto.getNumber();
Integer result = value != null ? value : 100;

我想弄清楚在方法有副作用或依赖于可变状态时,第一种做法在根本上是否不安全。

解决方案

  1. 是的,这是有保证的。你可以在Java语言规范的 §15.25找到相关描述 https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.25
  2. 当若能证明调用无副作用且状态未改变时,JIT编译器可能会进行优化。但这是实现细节,绝不要依赖它;并且它不适用于涉及I/O、数据库访问或可变状态的场景。
  3. 是的,在你的场景中,这将是最佳实践。如果在这种情况下进行数据库检查,第一种做法可能不安全,因为两次求值之间存在时间差,数据库中的条目可能会被改变。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章