此处讨论的运算符称为后缀增量运算符(JLS 15.14.2)。它被指定到的行为如下:
- 在运行时,如果操作数表达式的计算突然完成,那么后缀递增表达突然完成出于同样的原因,并没有增量发生。
- 否则,将值1添加到变量的值中,并将总和存回变量。
- 在添加之前,对值1和变量的值执行二进制数值提升(第5.6.2节)。
- 如有必要,总和通过缩小原始转换(§5.1.3)和/或受到装箱转换(§5.1.7)变为存储前的变量类型。
- 后缀增量表达式的值是存储新值之前的变量的值。
最后一点是这个问题的关键是:你为什么不能做arr[i]++ = v;
的道理是一样的确切原因,为什么你不能这样做x++ = v;
;后缀增量表达式返回值,而不是变量。
从JLS 15.1 Evaluation, Denotation and Result:
当在程序中的表达式求值(执行),所述结果表示三种情况之一:
- 可变[...](在C,这将被称为左值)
- 值[...]
- 无(表达被认为是无效)
的分配需要在左手侧的可变和值不是一个变量,这就是为什么你不能这样做x++ = v;
。
从JLS 15.26 Assignment Operators:
赋值操作符的第一操作数的结果必须是一个变量或编译时错误发生。这个操作数可能是一个命名变量[...],或者它可能是一个计算变量,可能来自字段或数组访问。 [...]
下面的代码片段显示错误尝试分配给值,从相当微妙要更明显:
int v = 42;
int x = 0;
x = v; // OKAY!
x++ = v; // illegal!
(x + 0) = v; // illegal!
(x * 1) = v; // illegal!
42 = v; // illegal!
// Error message: "The left-hand side of an assignment must be a variable"
请注意,您可以使用的后缀递增运算符某处位于赋值运算符的左侧,只要最终结果是一个变量。
int[] arr = new int[3];
int i = 0;
arr[i++] = 2;
arr[i++] = 3;
arr[i++] = 5;
System.out.println(Arrays.toString(arr)); // prints "[2, 3, 5]"
在java代码中从来没有见过这种编码风格(带方括号内的空格)。 – Roman 2010-03-14 20:31:11
作为一个方面说明,++运算符的字节码取决于它是否用于本地int变量,以及是否使用结果。最简单的情况是生成一个本地int变量的简单增量,在该变量中生成单个增量指令。你在提交数组成员后会生成一些最复杂的字节码。(我不能评论任何JIT转换。) – Neil 2010-03-14 21:54:32