对 i++ 的理解

引入

我们先看一个小的代码:

	int i = 0 ;
    int j = i ++ ;
    System.out.println( "i = " + i + ","+ "j = " + j);

	// 再看这个
	int i= 0 ;
	i = i ++ ;
	System.out.println( "i = " + i );

	// Console 
	i = 1,j = 0
	i = 0

	Process finished with exit code 0

笔者一开始认为下面的输出也是

	i = 1 

毕竟不管有没有赋值给 i , i++操作都对 i 做了++ 操作,可是现实总是残酷的对待笔者。虽然接触Java没那么长就,但好歹也是我大学的最好时光的终结者。现在对于这个问题的分析,一开始想要Debug的,后来发现,特么的,怎么Debug?所以就直接看 .class文件。

i++ 与 ++i

在分析 i++ 之前,我们经常遇到 ++i 的问题。这里笔者想说 ,我们初学者就记住一句话 ,i ++ 先赋值再运算 , ++ 先运算在赋值。因此呢,在我们的程序中,遇到了 i++ 与 ++i的单飞,都是一样的,大家都 ++ 了 , 也就没啥子区别了。这也是为什么在 for循环里面无论是 i++ ,还是 ++ i都可以的原因 , 因为到最后 i 都加了 , 这就够了。

但是仅限初学者啊,因为这个解释是最简单的,也是最直观的解释,对于其他的,还是关注一下底层的原理实现还是比较好的。

可以这么说 , 上面的 i++ 的先赋值在运算可以解决90%的问题,但是唯有那10%有点解释不通。所以我们还需要换种方式对他做介绍。之所以我们在初学的时候用上面哪种方式介绍,是因为,换种方式介绍你还回学Java吗?

从.class关注 i++ 问题

.class文件是什么

在我们一开始写HelloWorld.java的时候,我们都知道java文件在编译的时候会产生一个.class的字节码文件,他其实就是一个二进制文件,也正是因为它的存在,我们才能实现Java跨平台的交易。我们在打开这个.class文件

 	public Operate() {
    }

    public static void main(String[] args) {
        int i = 0;
        byte var10000 = i;
        int i = i + 1;
        int j = var10000;
        System.out.println("i = " + i + ",j = " + j);
        i = 0;
        var10000 = i;
        i = i + 1;
        i = var10000;
        System.out.println("i = " + i);
    }
很遗憾,我们看到的不是二进制文件,而是经过反编译的后的文件。

i++分析

我们直接看下面的,那个折磨笔者 i = i++ 问题。

1、初始化 i= 0 操作,都没有意见吧
2、这里呢,它们引入了一个第三方变量,也就是所谓二点第三者插足,将 i 值赋给 var10000 , 此时的 var10000 = 0 ;
3、现在开始对 i 做 ++ 操作 , 即 i = i + 1 -> i = 1 ;
4、第三者又回来了,将var10000的值又给了 i 。所以 随后的输出的 i = 0 .

那现在就知道了,不是我们没有做 ++ 操作 , i 的 值也的确变成了 1 , 但是很遗憾的是因为第三者的存在,它跟第三者跑了。我终于知道为啥小三这么可恶了,程序人生程序人生呀。

字节码分析

D:\development_tools\java\jdk1.8.0_201\bin\javap.exe -c com.test.Operate
Compiled from "Operate.java"
public class com.test.Operate {
  public com.test.Operate();
    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: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: new           #3                  // class java/lang/StringBuilder
      13: dup
      14: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      17: ldc           #5                  // String i =
      19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      22: iload_1
      23: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      26: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      29: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      32: return
}

Process finished with exit code 0

这里的分析就要涉及到内存的分析了。笔者还不熟悉这一块的内容,后续再补上。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值