在Java中,增量后运算符如何在返回语句中起作用?
给定下面的代码,ixAdd会做您期望的事情吗。E在递增之前返回ix的值,但在离开函数之前递增类成员在Java中,增量后运算符如何在返回语句中起作用?,java,operators,Java,Operators,给定下面的代码,ixAdd会做您期望的事情吗。E在递增之前返回ix的值,但在离开函数之前递增类成员 class myCounter { private int _ix = 1; public int ixAdd() { return _ix++; } } 我不确定当程序离开函数的堆栈帧(或Java中的任何内容)时,增量后/增量前的常规规则是否也适用于返回语句。是的,即使在返回语句中,常规规则也适用于增量后。基本上,它将在低级别执行的操作是将返回
class myCounter {
private int _ix = 1;
public int ixAdd()
{
return _ix++;
}
}
我不确定当程序离开函数的堆栈帧(或Java中的任何内容)时,增量后/增量前的常规规则是否也适用于返回语句。是的,即使在返回语句中,常规规则也适用于增量后。基本上,它将在低级别执行的操作是将返回值存储到寄存器中,然后递增类成员,然后从方法返回
您可以在显示字节码的问题中看到这一点。关键部分是,表达式求值后立即发生后增量/减量。它不仅发生在返回发生之前,而且发生在对任何后续表达式求值之前。例如,假设您编写了:
class myCounter {
private int _ix = 1;
public int ixAdd()
{
return _ix++ + giveMeZero();
}
public int giveMeZero()
{
System.out.println(_ix);
return 0;
}
}
这也会打印出递增的结果,因为递增发生在调用giveMeZero()
之前。是的,它发生了
但是不要这样做,在表达式中产生副作用是不好的风格。好吧,让我们看看字节码(使用
javap-c
自己查看):
从“PostIncTest.java”编译而来
类myCounter扩展了java.lang.Object{
myCounter();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:aload_0
5:iconst_1
6:putfield#2;//字段_ix:I
9:返回
公共int ixAdd();
代码:
0:aload_0
1:dup
2:getfield#2;//字段_ix:I
5:dup_x1
6:iconst_1
7:iadd
8:putfield#2;//字段_ix:I
11:我轮到你了
}
如您所见,
ixAdd()
中的说明6和7处理返回之前的增量。因此,正如我们所期望的,减量运算符在return语句中使用时确实有效果。但是,请注意,在这两条指令出现之前有一条dup
指令;递增的值(当然)不会反映在返回值中。它会在递增之前返回值,然后再递增ix。因此,在myCounter实例上第一次调用方法ixAdd时,它将返回1,第二次将返回2,依此类推。ehm。。你的意思是,像在我的编辑器中粘贴上面的代码并运行它?我不知道,对不起-p我去给自己拿杯咖啡…投票支持close。。。我以为作者可以马上关闭它?嘿,现在我知道为什么我没有尝试:得到乔恩·斯基特的答案。它实际上比这个问题更有用。@PT有趣的是,它本来很容易尝试:)谢谢你的回答,乔恩。正如PaulTomblin指出的那样,在我的编辑器中而不是在帖子中键入代码也可以解决这个问题。但是现在我从中得到的比我要求的更多。@Jon:对于从C到Java的人来说(这将是很多人),这是一件值得指出的事情。作为一个很长很长时间第一次使用C的Java用户,我不知道Java比C更清楚地定义了++的工作原理。我学会了避免“聪明”++使用C!它不仅发生在返回发生之前,而且如果返回语句是局部变量,它也不会返回递增的值。您的示例显示了一个全局变量。@ernesto:它没有任何区别:return语句返回表达式的值,该值将是预增量值。无论它使用局部变量还是字段,这都是一样的。该字段用于显示giveMeZero
方法观察递增的值。这里的副作用是非常有意的,我看不出它有什么害处。
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
}