在Java中,后增量运算符(i++)和前增量运算符(++i)如何工作?

139

你能解释一下这段 Java 代码的输出结果吗?

int a=5,i;

i=++a + ++a + a++;
i=a++ + ++a + ++a;
a=++a + ++a + a++;

System.out.println(a);
System.out.println(i);

两种情况的输出都是20


20
尽量避免含糊不清的陈述 :) - Prasoon Saurav
12
与C和C++不同,Java和C#有严格定义的评估顺序,因此这些语句不会产生歧义。 - Pete Kirkham
14
我知道,但是那些陈述并不(不能)用于实际目的,因此必须避免使用它们。 - Prasoon Saurav
9
@PeteKirkham 六年过去了,但我仍想指出,在这种情况下,“ambiguous”是含糊不清的——它可能意味着“编译器不知道该放什么”,也可能意味着“程序员不知道它的含义”。 - anon
i=++a + ++a + a++; => i=7 + 8 + 5; (a=8) 因为后置自增运算符具有最高的优先级,这意味着应该首先执行 a++。 - rsirs
显示剩余3条评论
14个回答

268

++a会先增加变量的值,然后再使用它。
a++会先使用变量的值,然后再增加它。

如果你有

a = 1;

而且你这样做

System.out.println(a++); //You will see 1

//Now a is 2

System.out.println(++a); //You will see 3

codaddict explains你特定的代码片段。


2
我认为,与其使用“uses”,一个更不容易引起混淆的词语应该是“评估”。 - Ojonugwa Jude Ochalifu

175

这有帮助吗?

a = 5;
i=++a + ++a + a++; =>
i=6 + 7 + 7; (a=8)

a = 5;
i=a++ + ++a + ++a; =>
i=5 + 7 + 8; (a=8)

关键在于++a会先将值加1然后立即返回。

a++也会将值加1(在后台完成),但是它返回的是变量未改变前的值,这看起来像是稍后才执行。


5
第二个条件中,a是否确实等于9? - Pete Kirkham
1
i=7 + 8 + 5; (a=8) 因为后置自增运算符具有最高的优先级,所以 a++ 先执行吗? - rsirs
5
将复杂的例子简化为易于解释的内容。 - oznus
这个答案对于C#和C++是一样的吗? - workoverflow
1
@Dennis b = a++ 的结果是 b = 1, a = 2,然后 c = ++b 的结果是 c = 2, b = 2 - Andreas

80

在这两种情况下,首先计算值,但是在后缀增量中它保留旧值,并在计算后返回它。

++a

  1. a = a + 1;
  2. 返回 a;

a++

  1. temp = a;
  2. a = a + 1;
  3. 返回 temp;

26
i = ++a + ++a + a++;

i = 6 + 7 + 7

工作: 将a增加到6(当前值为6)+将a增加到7(当前值为7)。总和现在是13,将其添加到a的当前值(= 7),然后将a增加到8。总和为20,分配完成后a的值为8。

i = a++ + ++a + ++a;

i = 5 + 7 + 8

工作中: 开始时a的值为5。将其用于加法并将其增加到6(当前值为6)。从当前值6开始将a递增至7,以获取+的另一个操作数。总和为12,a的当前值为7。接下来将a从7递增至8(当前值=8),并将其与先前的总和12相加,得到20。


这些语句是从右到左还是从左到右工作的? - Abhijeet

10

++a在对a进行运算之前会将其增加。 a++在对a进行运算后再将其增加。

与你所给出的表达式相关:

i = ((++a) + (++a) + (a++)) == ((6) + (7) + (7)); // a is 8 at the end
i = ((a++) + (++a) + (++a)) == ((5) + (7) + (8)); // a is 8 at the end

我上面使用的括号是Java隐式使用的。如果你从这个角度看这些术语,你可以很容易地看出它们是相同的,因为它们是可交换的。


1
@KlasLindbäck 可交换意味着您可以交换两个表达式并仍然获得相同的结果。因此,a++ + ++a == ++a + a++ (5 + 7 == 6 + 6; 最终 a == 7)。 - Aurril

8
在上面的例子中,
int a = 5,i;

i=++a + ++a + a++;        //Ans: i = 6 + 7 + 7 = 20 then a = 8 

i=a++ + ++a + ++a;        //Ans: i = 8 + 10 + 11 = 29 then a = 11

a=++a + ++a + a++;        //Ans: a = 12 + 13 + 13 = 38

System.out.println(a);    //Ans: a = 38

System.out.println(i);    //Ans: i = 29

在C++中,a是39。为什么呢? - undefined

6

我认为,如果你将所有语句组合并在Java 8.1中运行,你会得到不同的答案,至少这是我的经验。

代码将按以下方式工作:

int a=5,i;

i=++a + ++a + a++;            /*a = 5;
                                i=++a + ++a + a++; =>
                                i=6 + 7 + 7; (a=8); i=20;*/

i=a++ + ++a + ++a;           /*a = 5;
                                i=a++ + ++a + ++a; =>
                                i=8 + 10 + 11; (a=11); i=29;*/

a=++a + ++a + a++;            /*a=5;
                                a=++a + ++a + a++; =>
                                a=12 + 13 + 13;  a=38;*/

System.out.println(a);        //output: 38
System.out.println(i);         //output: 29

是的,这是唯一正确的答案,对应于提供的糟糕代码。其他人已经解释了代码,使其成为一个合法的有效问题。 - Tristan

6

++a是前缀递增运算符:

  • 首先计算并存储结果,
  • 然后使用变量。

a++是后缀递增运算符:

  • 首先使用变量,
  • 然后计算并存储结果。

一旦你记住了规则,计算就变得简单易懂!


4

假设您的意思是

int a=5; int i;

i=++a + ++a + a++;

System.out.println(i);

a=5;

i=a++ + ++a + ++a;

System.out.println(i);

a=5;

a=++a + ++a + a++;

System.out.println(a);

这将被评估为:

i = (6, a is now 6) + (7, a is now 7) + (7, a is now 8)

因此,i的值为6 + 7 + 7 = 20,所以输出为20。

i = (5, a is now 6) + (7, a is now 7) + (8, a is now 8)

因此,我是 5 + 7 + 8 = 20,所以再次打印出 20。

a = (6, a is now 6) + (7, a is now 7) + (7, a is now 8)

在右侧所有内容被评估之后(包括将a设置为8),然后将a设置为6 + 7 + 7 = 20,因此最后打印出20。


3
a 为 5 时,a++ 先将 5 赋给表达式,然后再将 a 加 1;而 ++a 则是先将 a 加 1,再将结果传递给表达式(在这种情况下,表达式得到的是 a 的值 6)。
因此,你可以计算:
i = 6 + 7 + 7
i = 5 + 7 + 8

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接