i++ 与 ++i 的从字节码层面看二者的区别

时间:2022-05-23 05:15:11

/**
* javap命令可以对class反汇编得到其字节码文件(此命令并不是jdk8开始的,只不过jdk8中对工具进行加强,增加了一些参数,可通过 javap -help了解)
*
* 注意:
* 字节码文件在虚拟机中是通过栈帧来保存指令的,也称为操作栈,是一个后入先出的栈。并不是针对寄存器的直接操作。
* 字节码执行引擎通过操作站获取指令。
*
* 这个测试同时验证了 ++i 和 i++的区别。
* ++i,在字节码层面,会先进行iinc,也就是执行自增,然后load变量
* i++,则是,先load变量,后自增(因为已经load,所以本次自增,并不会影响已经load的变量值)。
*
* @author zhuotao
*
*/
public class JavapTest {

/**
* 最简单的求和操作,javap反汇编得到的字节码如下:
Code:
0: iload_1 // 第一个int类型变量
1: iload_2 // 第二个int类型变量
2: iadd // 执行int类型的add操作
3: ireturn // 返回int类型
*
*/
public int add(int a, int b) {
  return a+b;
}

/**
* 字节码如下:
* Code:
0: iload_1 // int类型变量
1: iconst_1 // int类型常量1
2: iadd // int类型add
3: ireturn // 返回
* @param a
* @return
*/
public int incr(int a) {
  return a+1;
}

/**
* 字节码如下:
* Code:
0: iload_1 // int类型变量
1: iinc 1, 1 // iinc 局部变量自增 第一个“1” 表示int类型变量索引, 第二个“1”表示+1
4: ireturn // 返回
* @param a
* @return
*/
public int incr1(int a) {
  return a++;
}

/**
* 用两个变量,来验证iinc的参数分别表示什么
* 字节码如下:
* Code:
0: iinc 2, 1 // “2”表示参数列表的第二个参数, "1"表示步长
3: iload_2 // load第二个int类型参数
4: ireturn // 返回load变量
*/
public int incr2(int a, int b) {
  return ++b;
}

/**
* 这个方法字节码同incr2
* 字节码如下:
* Code:
0: iinc 1, 1
3: iload_1
4: ireturn
*/
public int incr3(int a) {
  a++;
  return a;
}

public static void main(String[] args) {
  System.out.println(new JavapTest().incr1(2)); // return a++; 返回的是2,也就是先使用后加。
  System.out.println(new JavapTest().incr2(0,2)); // return ++a; 返回的是3,也就是先加后使用。
  System.out.println(new JavapTest().incr3(2));
}
}