我有以下代码:

public class Tests {
    public static void main(String[] args) throws Exception {
        int x = 0;
        while(x<3) {
            x = x++;
            System.out.println(x);
        }
    }
}

我们知道他应该只写x++或x=x+1,但在x=x+ +时,它应该先把x归为自己,然后再加1。为什么x的值是0 ?

- - -更新

下面是字节码:

public class Tests extends java.lang.Object{
public Tests();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[])   throws java.lang.Exception;
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   iconst_3
   4:   if_icmpge   22
   7:   iload_1
   8:   iinc    1, 1
   11:  istore_1
   12:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   15:  iload_1
   16:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
   19:  goto    2
   22:  return

}

我会仔细阅读说明,试着理解……


当前回答

其他人已经解释得很好了。我只包含了指向相关Java规范部分的链接。

X = x++是一个表达式。Java将遵循求值顺序。 它将首先计算表达式x++,该表达式将增加x并将结果值设置为x的前一个值。 然后它将表达式结果赋值给变量x。最后,x返回到它之前的值。

其他回答

从http://download.oracle.com/javase/tutorial/java/nutsandbolts/op1.html

The increment/decrement operators can be applied before (prefix) or after (postfix) the operand. The code result++; and ++result; will both end in result being incremented by one. The only difference is that the prefix version (++result) evaluates to the incremented value, whereas the postfix version (result++) evaluates to the original value. If you are just performing a simple increment/decrement, it doesn't really matter which version you choose. But if you use this operator in part of a larger expression, the one that you choose may make a significant difference.

为了说明这一点,请尝试以下方法:

    int x = 0;
    int y = 0;
    y = x++;
    System.out.println(x);
    System.out.println(y);

它会输出1和0。

这是因为在这种情况下它永远不会增加。x++会先使用它的值,然后再进行递增,在这种情况下,它会像这样:

x = 0;

但如果你用++x;这将会增加。

我想知道Java规范中是否有精确定义此行为的内容。(这句话的明显意思是我懒得去检查。)

注意Tom的字节码,关键行是7、8和11。第7行将x加载到计算堆栈中。第8行增加x。第11行将堆栈的值存储回x。在正常情况下,如果你不将值赋值回自身,我不认为有任何理由不能加载,存储,然后增加。你会得到同样的结果。

比如,假设你有一个更正常的情况,你写这样的东西: z = (x + +) + (y + +);

它是否说(跳过技术细节的伪代码)

load x
increment x
add y
increment y
store x+y to z

or

load x
add y
store x+y to z
increment x
increment y

应该无关紧要。我认为,任何一种实现都是有效的。

我会非常谨慎地编写依赖于这种行为的代码。对我来说,它看起来非常依赖于实现。只有当您做了一些疯狂的事情(比如这里的例子),或者您有两个线程正在运行,并且依赖于表达式中的求值顺序时,才会产生影响。

我想是因为在java++中有比=(赋值)更高的优先级…不是吗? 看看http://www.cs.uwf.edu/~eelsheik/cop2253/resources/op_precedence.html…

同理,如果x=x+1。+的优先级高于=(赋值)

这是因为x的值根本没有增加。

x = x++;

等于

int temp = x;
x++;
x = temp;

解释:

让我们看看这个操作的字节代码。考虑一个示例类:

class test {
    public static void main(String[] args) {
        int i=0;
        i=i++;
    }
}

现在运行类反汇编程序,我们得到:

$ javap -c test
Compiled from "test.java"
class test extends java.lang.Object{
test();
  Code:
   0:    aload_0
   1:    invokespecial    #1; //Method java/lang/Object."<init>":()V
   4:    return

public static void main(java.lang.String[]);
  Code:
   0:    iconst_0
   1:    istore_1
   2:    iload_1
   3:    iinc    1, 1
   6:    istore_1
   7:    return
}

现在Java虚拟机是基于堆栈的,这意味着对于每个操作,数据将被推入堆栈,从堆栈中,数据将弹出来执行操作。还有另一种数据结构,通常是存储局部变量的数组。局部变量的id是数组的索引。

让我们看看main()方法中的助记符:

iconst_0: The constant value 0 is pushed on to the stack. istore_1: The top element of the stack is popped out and stored in the local variable with index 1 which is x. iload_1 : The value at the location 1 that is the value of x which is 0, is pushed into the stack. iinc 1, 1 : The value at the memory location 1 is incremented by 1. So x now becomes 1. istore_1 : The value at the top of the stack is stored to the memory location1. That is 0 is assigned to x overwriting its incremented value.

因此,x的值不会改变,从而导致无限循环。