从OCP Java SE 6程序员实践考试的第280页开始,问题9:
int x = 3;
x = x++;
// x is still 3
在解释中我们可以读到:
x = x++;
线不会离开x == 4
,因为++
在分配发生后应用。
我同意x
是3,我理解增加后。
我不同意这个解释。我会用“之前”替换“之后”。
我认为它的工作方式如下:
x
是3。x++
被执行。我将此增量后运算符视为函数:
int operator++() {
int temp = getX();
setX(temp + 1);
return temp;
}
所以,在执行x++
之后,x
是4,但x++
表达式返回的值是3
。=
。只需将返回的3
写入x
。因此,在我的眼中,++
在分配发生之前应用。我错了吗?
...在分配发生后应用
++
。
好的坚持住。这实际上令人困惑,也许暗示了不正确的行为。
你有表达†:
x = ( x++ )
会发生什么(JLS 15.26.1):
x
左侧的表达式(生成变量)。( x++ )
右侧的表达式(生成一个值)。x
后递增,表达式的结果是x
的旧值。x
被赋予右侧评估产生的值,这是x
的旧值。所以后增量发生在赋值之前。
(因此,正如我们所知,在执行语句x
之后x = x++;
的值与执行语句之前的x
的值相同,即3
。)
因此,在我的眼中,
++
在分配发生之前应用。我错了吗?
你是对的。
从技术上讲,它的指定方式是在存储结果之前和赋值运算符的求值过程中对x++
进行求值。所以x++
可以被解释为在任务之前或期间发生。不是之后,所以这本书看起来都是错误的。
只是为了它,我们也可以看一些字节码:
/* int x = 3; */
iconst_3 // push the constant 3 on to the stack : temp = 3
istore_0 // pop the stack and store in local variable 0 : x = temp
/* x = x++; */
iload_0 // push local variable 0 on to the stack : temp = x
iinc 0 1 // increment local variable 0 by 1 : x = x + 1
istore_0 // pop the stack and store in local variable 0 : x = temp
iinc
发生在istore
之前。
†:括号对评估没有影响,它们只是为了清晰起见。
达到官方规范:
在赋值方面,这是简单的赋值,所以我们遇到了案例3:
x
x++
因此,在步骤2中,后缀运算符应该被解析,然后在步骤3中,x再次被赋予其原始值:
call: x = x++;
interframe: LHS is variable 'x'
interframe: RHS caches return value as 3
interframe: x is incremented to 4
interframe: RHS cached value '3' is returned for assignment
interframe: variable x is assigned value 3
call result: x = 3
所以我认为你的书是错的是正确的,并且可能值得联系作者或出版商以发布更正(或添加到勘误页等)
x ++表示“使用x然后递增x”。
您也可以使用++ x,这意味着“递增x然后使用x”。
但是,您可以更轻松地做到
x += 1;
++ x称为preincrement,而x ++称为postincrement。
int x = 3;
x = ++x;
例子
int x = 5, y = 5;
System.out.println(++x); // outputs 6
System.out.println(x); // outputs 6
System.out.println(y++); // outputs 5
System.out.println(y); // outputs 6