ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

懂得i++和++i

2020-05-24 12:56:36  阅读:302  来源: 互联网

标签:++ int 懂得 println istore iload public


懂得i++和++i

案例

代码1

package org.huangao.other.dome1;

import org.junit.Test;

public class Dome1 {
    @Test
    public void test1() {
        int j = 0;
        j = j++;
        System.out.println(j);
    }

    @Test
    public void test2() {
        int j = 0;
        j = ++j;
        System.out.println(j);
    }
}

结果

test1:0
test2:1

代码2

package org.huangao.other.dome1;

import org.junit.Test;

public class Dome1 {
    @Test
    public void test1() {
        int j = 0;
//        j = j++;
        j++;
        System.out.println(j);
    }

    @Test
    public void test2() {
        int j = 0;
//        j = ++j;
        ++j;
        System.out.println(j);
    }
}

结果

test1:1
test2:1

​ 可以初步分析是 j 值 对于 j++ 赋值的地方有所差异

分析

代码1的字节码

D:\jdk1.8.0_211\bin\javap.exe -c org.huangao.other.dome1.Dome1
Compiled from "Dome1.java"
public class org.huangao.other.dome1.Dome1 {
  public org.huangao.other.dome1.Dome1();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public void test1();
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: iinc          1, 1
       6: istore_1
       7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: iload_1
      11: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      14: return

  public void test2();
    Code:
       0: iconst_0
       1: istore_1
       2: iinc          1, 1
       5: iload_1
       6: istore_1
       7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: iload_1
      11: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      14: return
}

Process finished with exit code 0

分析

​ 首先我们先看test1 方法

iconst_0 代表将int型 0 推送至栈顶

istore_1 将栈顶 int 型数值存入第二个本地变量 即 j=0

iload_1 将第二个int 型本地变量 推送至栈顶 即 j=0

iinc 1,1 将局部变量表中1号元素自增1,此时j=1

istore_1 将栈顶 int 型数值存入第二个本地变量

getstatic

iload_1

invokevirtual

return

​ 接下来看test2方法

iconst_0 将 int 型 0 推入栈顶

istore_1 将栈顶 int 型 数值存入第二个本地变量

iinc 1,1 将局部变量表1 号元素 自增1 ,此时j=1

iload_1 将第二个 int 型本地变量推送至栈顶

istore_1 将栈顶 int 型数值 存入第二个本地变量

getstatic

.....

结论

本来局部变量表中的j已经完成了自增,但是在进行赋值的时候,是将操作栈中的数据弹出,直接进行覆盖操作

​ 如果站在JVM的层次来说 对于 i++ 和 ++i

  1. i++ 是先被操作数栈拿去了(先执行了load指令),然后再在局部变量表中完成了自增,但是操作数栈中还是自增前的值
  2. 而++i是在局部变量表中完成了自增(先执行了innc指令),然后再被load进行了操作数栈,所以操作数栈中保存的是自增后的值

课后思考

    @Test
    public void test3() {
        int i = 4;
        int b = i++;
        int a = ++i;
    }
    
    
      public void test3();
    Code:
       0: iconst_4
       1: istore_1
       2: iload_1
       3: iinc          1, 1
       6: istore_2
       7: iinc          1, 1
      10: iload_1
      11: istore_3
      12: return
    @Test
    public void test3() {
        int i = 4;
        i = i++;
        System.out.println(i);
        i = ++i;
        System.out.println(i);
    }
    4
    5
    
      public void test3();
    Code:
       0: iconst_4
       1: istore_1
       2: iload_1
       3: iinc          1, 1
       6: istore_1
       7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: iload_1
      11: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      14: iinc          1, 1
      17: iload_1
      18: istore_1
      19: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      22: iload_1
      23: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      26: return

    @Test
    public void test3() {
        int i = 4;
        i = ++i;
        System.out.println(i);
        i = i++;
        System.out.println(i);
    }
    
    5
    5
      public void test3();
    Code:
       0: iconst_4
       1: istore_1
       2: iinc          1, 1
       5: iload_1
       6: istore_1
       7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: iload_1
      11: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      14: iload_1
      15: iinc          1, 1
      18: istore_1
      19: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      22: iload_1
      23: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      26: return

标签:++,int,懂得,println,istore,iload,public
来源: https://www.cnblogs.com/huan30/p/12950612.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有