根据字节码探讨java自增运算符的原理

public class Test {
    
    static int x, y;

    public static void main(String args[]) {
        x++;
        myMethod();
        System.out.println(x + y + ++x);
    }

    public static void myMethod() {
        y = x++ + ++x;
    }
}

如果以上代码的结果你很自信能做对,那么本文或许对你帮助不大,但仍然可以看下java底层的实现.在最后将给出以上代码的结果以及解析.

本文中的例子主要针对以下情况:

①x=y++

②x=++y

③x=x++

④x=++x

a:x,y为形参

b:x,y为成员变量

废话不多说,直接上代码

代码1(①+b):

public   class Test {

    static int x,y;
    public static void main(String args[]){
        test();
    }

    public static void test(){
        x = y++;
        System.out.println(x+""+y);
    }
}

结果:01

test()字节码:

      0: getstatic     #3                  // Field y:I
         3: dup
         4: iconst_1
         5: iadd
         6: putstatic     #3                  // Field y:I
         9: putstatic     #4                  // Field x:I
        12: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        15: getstatic     #4                  // Field x:I
        18: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
        21: return

解释:

0:y(值)入操作栈

3:得到y(值)的一个快照y'(值)

(个人认为相当于是将栈顶元素也就是y(值)复制了一份,然后将复制得到的y'(值)入操作栈,现在操作栈中有y(值)和y'(值))

4:常量1入操作栈

5:常量1和y'(值)弹出栈,进行加操作,并将结果s入栈

6:将结果s弹出栈,赋给y(变量)(此时y==1)

9:将y(值)弹出栈,赋给x(变量)(此时x==0)

因为y(值)入操作栈之后没有修改,所以x依旧是0,而y变成了1

 

代码2(②+b):

public   class Test {

    static int x,y;
    public static void main(String args[]){
        test();
    }

    public static void test(){
        x = ++y;
        System.out.println(x+""+y);
    }
}

结果11

test()字节码:

      0: getstatic     #3                  // Field y:I
         3: iconst_1
         4: iadd
         5: dup
         6: putstatic     #3                  // Field y:I
         9: putstatic     #4                  // Field x:I
        12: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        15: getstatic     #4                  // Field x:I
        18: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
        21: return

解释:

0:y(值)入操作栈

3:常量1入操作栈

4:常量1和y(值)弹出栈,进行加操作,并将结果s入栈

5:得到栈顶元素也就是s的快照s',并入操作栈

6:将s'弹出栈,并赋给y(变量)(此时y==1)

9:将s弹出栈,并赋给x(变量)(此时x==1)

 

代码3(③+b):

public   class Test {

    static int x;
    public static void main(String args[]){
        test();
    }

    public static void test(){
        x = x++;
        System.out.println(x);
    }
}

结果:0

test()字节码:

      0: getstatic     #3                  // Field x:I
         3: dup
         4: iconst_1
         5: iadd
         6: putstatic     #3                  // Field x:I
         9: putstatic     #3                  // Field x:I
        12: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
        15: getstatic     #3                  // Field x:I
        18: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
        21: return

解释:

0:x(值)入操作栈

3:得到x(值)的快照x',入操作栈

4:常量1入操作栈

5:常量1和x'弹出操作栈,进行加操作,将结果s入操作栈

6:将s弹出栈,并赋给x(变量)(此时x==1)

9:将x(值)弹出栈,并赋给x(变量)(此时x的值被覆盖,x==0)

 

代码4(④+b):

public   class Test {

    static int x;
    public static void main(String args[]){
        test();
    }

    public static void test(){
        x = ++x;
        System.out.println(x);
    }
}

结果:1

test()字节码:

      0: getstatic     #3                  // Field x:I
         3: iconst_1
         4: iadd
         5: dup
         6: putstatic     #3                  // Field x:I
         9: putstatic     #3                  // Field x:I
        12: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
        15: getstatic     #3                  // Field x:I
        18: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
        21: return

解释:

0:x(值)入操作栈

3:常量1如入操作栈

4:常量1和x(值)弹出操作栈,进行加操作,并将结果s入操作栈

5:得到栈顶元素s的快照s',入操作栈

6.将s'弹出操作栈,并赋给x(变量)(此时x==1)

9:将s弹出操作栈,并赋给x(变量)(此时x==1)

 

代码5(①+a):

public   class Test {

    public static void main(String args[]){
        test(0,0);
    }

    public static void test(int x,int y){
        x = y++;
        System.out.println(x+""+y); } }

结果:01

test()字节码:

      0: iload_1
         1: iinc          1, 1
         4: istore_0
         5: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         8: new           #4                  // class java/lang/StringBuilder
        11: dup
        12: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
        15: iload_0
        16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        19: ldc           #7                  // String
        21: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        24: iload_1
        25: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        28: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        31: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        34: return

 

解释:

0:将本地变量区的y(值)入操作栈

1:将本地变量y加1(y==1)

4:将0中的y(值)弹出栈,并赋给本地变量区的x(x==0)

 

代码6(②+a):

public   class Test {

    public static void main(String args[]){
        test(0,0);
    }

    public static void test(int x,int y){
        x = ++y;
        System.out.println(x+""+y);
    }
}

结果:11

test()字节码:

      0: iinc          1, 1
         3: iload_1
         4: istore_0
         5: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         8: new           #4                  // class java/lang/StringBuilder
        11: dup
        12: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
        15: iload_0
        16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        19: ldc           #7                  // String
        21: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        24: iload_1
        25: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        28: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        31: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        34: return

解释:

0:将本地变量y加1(此时y==1)

3:将本地变量y(值)入操作栈

4:将y(值)弹出操作栈,并赋给x(此时x==1)

 

代码7(③+a):

public   class Test {

    public static void main(String args[]){
        test(0);
    }

    public static void test(int x){
        x = x++;
        System.out.println(x);
    }
}

结果:0

test()字节码:

      0: iload_0
         1: iinc          0, 1
         4: istore_0
         5: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         8: iload_0
         9: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
        12: return

解释:

0:本地变量x(值)入操作栈

1:本地变量x加1(此时x==1)

4:将x(值)弹出栈,并赋给本地变量x(此时x==0)

 

代码8(④+a):

public   class Test {

    public static void main(String args[]){
        test(0);
    }

    public static void test(int x){
        x = ++x;
        System.out.println(x);
    }
}

结果:1

test()字节码:

      0: iinc          0, 1
         3: iload_0
         4: istore_0
         5: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         8: iload_0
         9: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
        12: return

解释:

0:本地变量x加1(此时x==1)

3:本地变量x(值)入操作栈

4:将x(值)弹出操作栈,并赋给x(此时x==1) 

 

事实上i++和++i在底层的实现都是先自增,区别在于返回值.i++返回自增前的值,++i返回自增后的值

 

现在来看看一开始那段代码的结果和解析:

结果:11

myMethod()字节码:

      0: getstatic     #2                  // Field x:I
         3: dup
         4: iconst_1
         5: iadd
         6: putstatic     #2                  // Field x:I
         9: getstatic     #2                  // Field x:I
        12: iconst_1
        13: iadd
        14: dup
        15: putstatic     #2                  // Field x:I
        18: iadd
        19: putstatic     #5                  // Field y:I
        22: return

解释:

0:变量x(值)入操作栈(栈状态:x0)

3:得到栈顶元素x(值)的快照x'(值),并入操作栈(栈状态:x0->x0')

4:常量1入操作栈(栈状态:x0->x0'->1)

5:常量1和x'(值)弹出操作栈,进行加操作,将结果s0入操作栈(栈状态:x0->s0)

6:弹出s0,并赋给x(变量)(栈状态:x0,此时x(变量)==2)

9:将修改后的x(值)入操作栈(栈状态:x0->x1)

12:常量1入操作栈(栈状态:x0->x1->1)

13:常量1和X1(值)弹出操作栈,进行加操作,将结果s1入操作栈(栈状态:x0->s1)

14:得到栈顶元素s1(值)的快照s1'(值),并入操作栈(栈状态:x0->s1->s1')

15:弹出s1'并赋给x(变量)(栈状态:x0->s1)

18:s1和x0弹出栈,进行加操作,将结果s2入栈(栈状态:s2)

19:弹出s2,并赋给y(变量) 

所以在myMethod之后x的值为经过两次自增后的值,为x+2==3,而y的值为x0+s1,其中x0为最初传进来的值==1,s1是x经过两次自增后的值==3,所以y==4

x==3,y==4

最后输出的结果就是3+4+4==11

转载请注明出处:http://www.cnblogs.com/vinozly/p/5401698.html

 

 

转载于:https://www.cnblogs.com/vinozly/p/5401698.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值