Java中自增操作符是如何实现自动增加变量值的?

2026-05-19 12:111阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1740个文字,预计阅读时间需要7分钟。

Java中自增操作符是如何实现自动增加变量值的?

Java自增+本文字分为以下部分:- 标子- 标子解释- 来点复杂的- 字节码解读- 总结- 标子Java存在一种神奇的运算符,C++自增1,但经常分不清i++和++i的区别,当然最后的结果可能都是i。

Java自增

本文分为以下部分:

  • 栗子
  • 栗子解释
  • 来点复杂的
  • 字节码解读
  • 总结
栗子

java存在一种神奇的操作符,++,自增1,但是经常分不清楚 i++++i 两者的区别,虽然最后结果可能都是 i+1,但是在不同场景使用有不同效果。先上一段代码。

public class IncreaseTest { public static void main(String[] args) { int i = 10; int j = i++; System.out.println(j); int k = ++i; System.out.println(k); } }

看着脑袋都大,感觉 j、k 最后值都一样,实际上不一样。在讲解原理之前,先简单说明一下底层东西。

局部变量表

oracle java 局部变量表 中解释

其中第二段解释,byte、char、short、int 等基本数据类型值会存在局部变量表中。

操作数栈

oracle java 操作数栈 中解释

简单理解就是 主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。就是用于计算等操作。

举个简单的栗子简单解释上面两个东西

/** * 操作数栈压入 10 这个值 * 然后将 10 保存到本地变量表赋值给 i * j同理 * * 在进行 k = i + j 的操作 * 操作数栈从本地变量表中读取 i 的值压入操作数栈 * 操作数栈从本地变量表中读取 j 的值压入操作数栈 * 然后对操作数栈中的两个值进行相加操作 * 将结果保存到本地变量表同时赋值给 k * 最后输出 本地变量表中 读取的数据 */ public static void main(String[] args) { int i = 10; int j = 20; int k = i + j; System.out.println(k); }

图例如下:

Java中自增操作符是如何实现自动增加变量值的?

栗子解释

回归正题,最初的栗子,在计算 j 的时候,是先将 i 的本地变量表的值取出来压入操作数栈,然后再进行 ++ 、赋值等操作,那是先赋值还是先 ++ 呢,其实已经不重要了,因为 ++ 操作操作的是本地变量表的值,而不是操作数栈中的值,所以当 i 的值已经压入操作数栈后,那么操作数栈中的值已经是 10 了,就算本地变量表的值再变化,不会改变操作数栈中的值。所以 j 为 10,本地变量表中 i 为11。(事实上是i的值取出来压入操作数栈,然后i的本地变量表进行+1操作,然后操作数栈赋值给j)

然后第二步,进行的是 int k = ++i;

首先看到的是 ++,所以操作的是本地变量表 i+1 ,然后再将 i 的本地变量表值压入操作数栈,再赋值给 k。

所以 i++ ,是先将 i 的值压入操作数栈,再将本地变量表中 i 的值 +1 ,再将操作数栈中的数值赋值给要赋值的对象。

++i ,是先将本地变量表中 i 的值 +1,再压入操作数栈中,再进行赋值给对象等操作。

简记:先++就是先+1,后++就是后+1。

来点复杂的

public class IncreaseTest2 { public static void main(String[] args) { int i = 10; i = i++; System.out.println(i); i = ++i; System.out.println(i); } }

首先看 i = i++;

通过简单的栗子,我们知道,当 i++ 再后面时,为后 ++;那么是 i 先赋值给自己 ,再 +1?

当然不是,仔细看上方赋值给 j 的图会发现,先本地变量 +1 ,再进行赋值。

然后再看 ++i,和第一个栗子差不多

字节码解读 第一个栗子

在终端中使用 javap -v -p xxx.class 文件可以看到该class文件的字节码文件。由于不好阅读,所以追加覆盖到 test1.txt 文件中。(采用idea的 jclasslib 插件也可以)

在文件中找到熟悉的public static void main,下面即为代码的字节码,我贴一部分

感觉有点晦涩难懂,我一一解释吧。

bipush 将数值(当前10位byte,-128—127均为byte)压入操作数栈。

istore 将操作数栈栈顶的值弹出返回给本地变量表(保存到本地变量)。

iload 从本地变量表中读取数值压入操作数栈。

iinc 本地变量表中的值+1

0: bipush 10 //操作数栈压入10 2: istore_1 //将10存储到本地变量i (这里1表示i,可以从文件下方LocalVariableTable查看) 3: iload_1 //读取i的值 10 压入操作数栈 4: iinc 1, 1 //本地变量中 i 的值 +1(操作数栈值不变,依旧为10) 7: istore_2 //操作数栈栈顶(10)的值弹出返回本地变量 j ,所以 j 为10 11: iload_2 //有个打印输出流,需要读取 j 的值,删除了相应字节码 15: iinc 1, 1 //本地变量 i 的值 +1(原本为11,现在变为12) 18: iload_1 //读取i的值 12 压入操作数栈 19: istore_3 //保存至 k ,所以 k 为12 第二个栗子

使用同样方法查看字节码

其实和第一个栗子一样,可以自行理解。

特栗

public class IncreaseTest3 { public static void main(String[] args) { int i = 10; i = (i++) * (++i); //120 System.out.println(i); } }

其实再理解上方字节码或者图解,这个自然而然容易理解了

图解

字节码大概描述就是

iload //10 入操作数栈 iinc //本地变量 +1 (操作数栈中依旧为10) innc //本地变量继续 +1(此时为12) iload //12 入操作数栈 //然后进行乘法得到120 istore 总结

i++ ,是先将 i 的值压入操作数栈,再将本地变量表中 i 的值 +1 ,最后操作数栈的数进行操作。

++i ,是先将本地变量表中 i 的值 +1,再压入操作数栈中,最后操作数栈的数进行操作。

简单记忆:先++就是先+1,后++就是后+1。

本文共计1740个文字,预计阅读时间需要7分钟。

Java中自增操作符是如何实现自动增加变量值的?

Java自增+本文字分为以下部分:- 标子- 标子解释- 来点复杂的- 字节码解读- 总结- 标子Java存在一种神奇的运算符,C++自增1,但经常分不清i++和++i的区别,当然最后的结果可能都是i。

Java自增

本文分为以下部分:

  • 栗子
  • 栗子解释
  • 来点复杂的
  • 字节码解读
  • 总结
栗子

java存在一种神奇的操作符,++,自增1,但是经常分不清楚 i++++i 两者的区别,虽然最后结果可能都是 i+1,但是在不同场景使用有不同效果。先上一段代码。

public class IncreaseTest { public static void main(String[] args) { int i = 10; int j = i++; System.out.println(j); int k = ++i; System.out.println(k); } }

看着脑袋都大,感觉 j、k 最后值都一样,实际上不一样。在讲解原理之前,先简单说明一下底层东西。

局部变量表

oracle java 局部变量表 中解释

其中第二段解释,byte、char、short、int 等基本数据类型值会存在局部变量表中。

操作数栈

oracle java 操作数栈 中解释

简单理解就是 主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。就是用于计算等操作。

举个简单的栗子简单解释上面两个东西

/** * 操作数栈压入 10 这个值 * 然后将 10 保存到本地变量表赋值给 i * j同理 * * 在进行 k = i + j 的操作 * 操作数栈从本地变量表中读取 i 的值压入操作数栈 * 操作数栈从本地变量表中读取 j 的值压入操作数栈 * 然后对操作数栈中的两个值进行相加操作 * 将结果保存到本地变量表同时赋值给 k * 最后输出 本地变量表中 读取的数据 */ public static void main(String[] args) { int i = 10; int j = 20; int k = i + j; System.out.println(k); }

图例如下:

Java中自增操作符是如何实现自动增加变量值的?

栗子解释

回归正题,最初的栗子,在计算 j 的时候,是先将 i 的本地变量表的值取出来压入操作数栈,然后再进行 ++ 、赋值等操作,那是先赋值还是先 ++ 呢,其实已经不重要了,因为 ++ 操作操作的是本地变量表的值,而不是操作数栈中的值,所以当 i 的值已经压入操作数栈后,那么操作数栈中的值已经是 10 了,就算本地变量表的值再变化,不会改变操作数栈中的值。所以 j 为 10,本地变量表中 i 为11。(事实上是i的值取出来压入操作数栈,然后i的本地变量表进行+1操作,然后操作数栈赋值给j)

然后第二步,进行的是 int k = ++i;

首先看到的是 ++,所以操作的是本地变量表 i+1 ,然后再将 i 的本地变量表值压入操作数栈,再赋值给 k。

所以 i++ ,是先将 i 的值压入操作数栈,再将本地变量表中 i 的值 +1 ,再将操作数栈中的数值赋值给要赋值的对象。

++i ,是先将本地变量表中 i 的值 +1,再压入操作数栈中,再进行赋值给对象等操作。

简记:先++就是先+1,后++就是后+1。

来点复杂的

public class IncreaseTest2 { public static void main(String[] args) { int i = 10; i = i++; System.out.println(i); i = ++i; System.out.println(i); } }

首先看 i = i++;

通过简单的栗子,我们知道,当 i++ 再后面时,为后 ++;那么是 i 先赋值给自己 ,再 +1?

当然不是,仔细看上方赋值给 j 的图会发现,先本地变量 +1 ,再进行赋值。

然后再看 ++i,和第一个栗子差不多

字节码解读 第一个栗子

在终端中使用 javap -v -p xxx.class 文件可以看到该class文件的字节码文件。由于不好阅读,所以追加覆盖到 test1.txt 文件中。(采用idea的 jclasslib 插件也可以)

在文件中找到熟悉的public static void main,下面即为代码的字节码,我贴一部分

感觉有点晦涩难懂,我一一解释吧。

bipush 将数值(当前10位byte,-128—127均为byte)压入操作数栈。

istore 将操作数栈栈顶的值弹出返回给本地变量表(保存到本地变量)。

iload 从本地变量表中读取数值压入操作数栈。

iinc 本地变量表中的值+1

0: bipush 10 //操作数栈压入10 2: istore_1 //将10存储到本地变量i (这里1表示i,可以从文件下方LocalVariableTable查看) 3: iload_1 //读取i的值 10 压入操作数栈 4: iinc 1, 1 //本地变量中 i 的值 +1(操作数栈值不变,依旧为10) 7: istore_2 //操作数栈栈顶(10)的值弹出返回本地变量 j ,所以 j 为10 11: iload_2 //有个打印输出流,需要读取 j 的值,删除了相应字节码 15: iinc 1, 1 //本地变量 i 的值 +1(原本为11,现在变为12) 18: iload_1 //读取i的值 12 压入操作数栈 19: istore_3 //保存至 k ,所以 k 为12 第二个栗子

使用同样方法查看字节码

其实和第一个栗子一样,可以自行理解。

特栗

public class IncreaseTest3 { public static void main(String[] args) { int i = 10; i = (i++) * (++i); //120 System.out.println(i); } }

其实再理解上方字节码或者图解,这个自然而然容易理解了

图解

字节码大概描述就是

iload //10 入操作数栈 iinc //本地变量 +1 (操作数栈中依旧为10) innc //本地变量继续 +1(此时为12) iload //12 入操作数栈 //然后进行乘法得到120 istore 总结

i++ ,是先将 i 的值压入操作数栈,再将本地变量表中 i 的值 +1 ,最后操作数栈的数进行操作。

++i ,是先将本地变量表中 i 的值 +1,再压入操作数栈中,最后操作数栈的数进行操作。

简单记忆:先++就是先+1,后++就是后+1。