15

给定下面的代码,ixAdd 会做你所期望的,即在递增之前返回 ix 的值,但在离开函数之前递增类成员?

class myCounter {
    private int _ix = 1;

    public int ixAdd()
    {
        return _ix++;
    }
}

当程序离开函数的堆栈框架(或Java中的任何内容)时,我不太确定后/前增量的通常规则是否也适用于返回语句。

4

5 回答 5

28

关键部分是在计算表达式后立即发生后递增/递减。它不仅发生在返回发生之前 - 它发生在任何以后的表达式被评估之前。例如,假设您写道:

class myCounter {
    private int _ix = 1;

    public int ixAdd()
    {
        return _ix++ + giveMeZero();
    }

    public int giveMeZero()
    {
        System.out.println(_ix);
        return 0;
    }
}

这也会打印出递增的结果,因为递增发生在giveMeZero()调用之前。

于 2009-03-17T15:26:20.400 回答
16

好吧,我们看一下字节码(javap -c <classname>自己用来看):

Compiled from "PostIncTest.java"
class myCounter extends java.lang.Object{
myCounter();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   iconst_1
   6:   putfield    #2; //Field _ix:I
   9:   return

public int ixAdd();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #2; //Field _ix:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #2; //Field _ix:I
   11:  ireturn

}

如您所见,指令 6 和 7 在ixAdd()返回之前处理增量。因此,正如我们所预料的那样,减量运算符在 return 语句中使用时确实有效果。但是请注意,dup在这两个出现之前有一个指令;增加的值(当然)不会反映在返回值中。

于 2009-03-17T15:27:19.290 回答
1

是的,即使在退货声明中,通常的规则也适用于后期增量。基本上,它在低级别所做的是将返回值存储到寄存器中,然后递增类成员,然后从方法返回。

您可以在稍后对显示字节码的问题的回答中看到这一点。

于 2009-03-17T15:24:27.627 回答
1

是的,它确实。

但是不要那样做,在表达式中有副作用是不好的风格。

于 2009-03-17T15:26:36.280 回答
0

它确实返回递增之前的值,然后递增_ix。因此,第一次在 myCounter 实例上调用 ixAdd 方法时,它将返回 1,第二次将返回 2,以此类推。

于 2009-03-17T15:31:23.693 回答