为什么在对同一个getter调用两次时,三元运算符的行为会不同?
我在研究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并非一个简单的字段访问器——它内部包含逻辑,且可能依赖可变状态。把它放在这样的三元表达式中会导致结果不一致。
我的问题:
- Java语言规范是否保证条件表达式和所选分支表达式会分别独立求值?
- Java是否会进行任何优化以避免重复的方法调用?
- 当方法不是纯访问器时,将方法结果存储在局部变量中是否被认为是最佳实践?
例如:
Integer value = dto.getNumber();
Integer result = value != null ? value : 100;
我想弄清楚在方法有副作用或依赖于可变状态时,第一种做法在根本上是否不安全。
解决方案
- 是的,这是有保证的。你可以在Java语言规范的 §15.25找到相关描述 https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.25
- 当若能证明调用无副作用且状态未改变时,JIT编译器可能会进行优化。但这是实现细节,绝不要依赖它;并且它不适用于涉及I/O、数据库访问或可变状态的场景。
- 是的,在你的场景中,这将是最佳实践。如果在这种情况下进行数据库检查,第一种做法可能不安全,因为两次求值之间存在时间差,数据库中的条目可能会被改变。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。