【问题标题】:Increment in function overwritten by +=被 += 覆盖的函数增量
【发布时间】:2016-09-18 10:34:09
【问题描述】:

在三元运算符中调用的方法会增加一个变量并返回一个布尔值。当函数返回 false 时,该值将被还原。我希望变量为 1,但得到的却是 0。为什么?

public class Main {
    public int a=0;//variable whose value is to be increased in function
    boolean function(){
        a++;
        return false;
    }
    public static void main(String argv[]){
        Main m=new Main();
        m.a+=(m.function()?1:0);
        System.out.println(m.a);//expected output to be 1 but got a 0 !!!!!
    }
}

【问题讨论】:

  • 这不应该是未定义的行为吗?
  • 未定义行为是一个 C/C++ 概念。
  • @holidayCoder 号
  • @LukePark 您最初的陈述仍然不正确,这就是我要指出的。函数的返回值和三元运算符单独与m.a的结束值无关。事实上,+= 运算符以某种方式替换了 a 的后增量状态。
  • @PatrickRoberts 我最初的陈述没有错。我认为你误解了命令。替换值,几乎是在说m.a = 0 (the current value) + (potentially 1 or 0)。

标签: java variable-assignment increment ternary


【解决方案1】:

您在一次调用中对m.a 进行了两项操作;在main

m.a += (m.function()?1:0);

将a 的值推送到帧上,然后调用m.function()(返回false),因此三元组扩展为m.a += 0;(并将帧中的m.a 的值添加到0 并存储在 m.a)。因此该值在m.function() 中递增(然后在main 中reset)。这样想,

m.a = m.a + (m.function() ? 1 : 0);

m.a 的值是在评估m.function() 之前确定的(因此它是一个后递增操作)。对于你预期的结果,你可以这样做

m.a = (m.function() ? 1 : 0) + m.a;

【讨论】:

  • 为什么会这样评价?您能引用涵盖此内容的 JLS 资源吗?
  • 所以行为与堆栈调用有关?
  • 函数返回假,这意味着它是0,在操作中它是假的,所以m.function()?1:0也返回0??
  • 我可能不太清楚,它确实与三元无关,这是因为使用了后增量运算符。
  • docs.oracle.com/javase/specs/jls/se8/html/… 解释了如何评估复合作业 @JohnKugelman。
【解决方案2】:

基本上m.a += (m.function() ? 1 : 0)编译成

 int t = m.a; // t=0 (bytecode GETFIELD)
 int r = m.function() ? 1  : 0; // r = 0 (INVOKEVIRTURAL and, IIRC, do a conditional jump)
 int f = t + r; // f = 0 (IADD)
 m.a = f // whatever m.a was before, now it is 0 (PUTFIELD)

以上行为均在JLS 15.26.2 (JAVA SE 8 edition)中指定

【讨论】:

  • 赞成 +1 为你,但 -1 表示 JLS 在这方面犯规。
猜你喜欢
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 2015-01-23
  • 2021-02-22
  • 1970-01-01
  • 2012-10-07
  • 2012-08-09
相关资源
最近更新 更多