java的i++和++i

java的i++和++i

说来惭愧,最近在刷面试题,一道有关于i++和++i的题竟然做错了!网上查了一圈恍然大悟。下面结合我的理解来说说这个问题,避免面试踩坑啊。

准备接招吧

package com.example.demo;

/**
 * @Author: junwe
 * @Date: 2021/2/27 23:15
 */
public class Test {
    public static void main(String[] args) {
        int i = 6;
        i = i++;
        int j = i++;
        int k = i + ++i * i ++;
        System.out.println("i="+i);
        System.out.println("j=" + j);
        System.out.println("k=" + k);
    }
}

下面揭晓答案了

image-20210228170415439

如果和你想的一样,恭喜你不用再往下看了。

要做对这题,需要弄清楚局部变量和操作数栈。先看一下main方法对应的字节码(idea查看字节码:右键.class文件,open in terminal,在命令行输入javap -v 类名),“##”的部分是我加的注释。

 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=4, args_size=1
         0: bipush        6     #6入栈#
         2: istore_1		   #6出栈,赋值给第一个变量i。0-2对应代码int i = 6;#
         3: iload_1			   #第一个变量6入栈#
         4: iinc          1, 1  #第一个变量i=6+1,此时局部变量i=7#
         7: istore_1            #6出栈,赋值给第一个变量i,此时局部变量的值被覆盖为63-7对应代码i = i++;#
         8: iload_1             #第一个变量6入栈#
         9: iinc          1, 1  #第一个变量加一,此时局部变量i=7#
        12: istore_2            #6出栈,赋值给第二个变量j。此时j=68-12对应代码int j = i++;#
        13: iload_1			   #第一个变量7入栈#
        14: iinc          1, 1  #第一个变量加一,此时局部变量i=8#
        17: iload_1			   #第一个变量8入栈#		
        18: iload_1             #第一个变量8入栈#
        19: iinc          1, 1  #第一个变量加一,此时局部变量i=9#
        22: imul                #栈中的两个8分别出栈相乘后64入栈#
        23: iadd                #64和栈低的7出栈相加后71入栈#
        24: istore_3            #71出栈赋值给第三个变量k#

没看懂?再来一张图
image-20210228184559126

<think>我们被要求使用中文回答,并且按照给定的格式要求(行内数学表达式用$...$,独立公式用$$...$$)。用户的问题是关于Java中i++++i的举例说明。 根据提供的引用,我们可以总结如下: 1. i++(后置递增)++i(前置递增)在单独使用时效果相同,都是i的值增加1。 2. 当它们参与表达式运算时,区别在于: - i++:先使用i的原始值参与表达式运算,然后再将i的值增加1。 - ++i:先将i的值增加1,然后使用增加后的值参与表达式运算。 3. 另外,引用[3][4]提到,i++不能作为左值,而++i可以(在C++中可能更明显,但在Java中,两者都不能作为左值,因为Java中自增表达式的结果不是变量。实际上,在Java中,无论是i++还是++i,都不能作为左值。所以这一点在Java中并不适用,可能是引用中提到了C++的情况。因此我们在Java中主要关注行为上的差异:返回值不同。 我们还需要注意引用[5]中提到的整数溢出的特殊情况,但用户的问题主要是举例说明,所以我们先展示基本使用。 举例说明: 例1:单独使用 ```java int i = 5; i++; // i变成6 int j = 5; ++j; // j变成6 System.out.println(i); // 输出6 System.out.println(j); // 输出6 ``` 例2:参与运算 ```java int a = 5; int b = a++; // 先将a的值赋给b(b=5),然后a自增(a=6) System.out.println(a); // 6 System.out.println(b); // 5 int c = 5; int d = ++c; // 先将c自增(c=6),然后将自增后的值赋给d(d=6) System.out.println(c); // 6 System.out.println(d); // 6 ``` 例3:在表达式中 ```java int m = 5; int n = m++ + 10; // 先计算m++,返回5,所以n=5+10=15,然后m变成6 System.out.println(m); // 6 System.out.println(n); // 15 int p = 5; int q = ++p + 10; // 先计算++p,返回6,所以q=6+10=16,然后p变成6 System.out.println(p); // 6 System.out.println(q); // 16 ``` 例4:在循环中 在for循环中,我们通常使用i++++i作为步进,这时它们的效果是一样的,因为单独使用。 ```java // 以下两个循环都会执行5次,输出0到4 for (int i=0; i<5; i++) { System.out.println(i); } for (int i=0; i<5; ++i) { System.out.println(i); } ``` 但是,如果循环体中使用了这个计数器,那么就要注意: ```java int i = 0; while (i < 5) { System.out.println(i++); // 输出0,1,2,3,4,因为每次先输出当前i,然后i自增 } int j = 0; while (j < 5) { System.out.println(++j); // 输出1,2,3,4,5,因为每次先自增j,然后输出 } ``` 关于效率问题,引用[2]提到在Java中,i++需要一个临时变量来存储自增前的值,而++i不需要,因此++i效率更高。但现代编译器可能会优化,尤其在循环中,两者的效率可能没有区别。不过,为了代码清晰避免混淆,建议在循环中使用++i。 最后,关于引用[5]中提到的整数溢出问题:当i为整型的最大值(Integer.MAX_VALUE,即2147483647)时,i+1会变成整型的最小值(Integer.MIN_VALUE,即-2147483648),因此会出现i+1小于i的情况(因为负数小于正数)。所以,在循环中如果i可能达到最大值,继续自增会导致变成最小值,从而可能引起无限循环。但用户问题主要是举例说明,所以我们不展开,但可以提一下。 因此,在回答中可以这样组织: 1. 介绍基本概念区别。 2. 给出几个例子说明单独使用参与运算时的不同。 3. 在循环中的使用举例。 4. 简要提及效率问题整数溢出的特殊情况。 注意:引用标记要放在相关内容的末尾。 </think> ### Java中i++++i的举例说明 在Java中,`i++`(后置递增)`++i`(前置递增)的主要区别在于**表达式的返回值****自增时机**。以下是具体说明代码示例: #### 1. **基本区别** - **`i++`**:先返回变量当前值,再执行自增操作 表达式值 = 原始值,执行后 i 增加1 - **`++i`**:先执行自增操作,再返回变量值 表达式值 = 自增后的值 #### 2. **代码示例** ```java // 示例1:单独使用(效果相同) int a = 5; a++; // a变为6 int b = 5; ++b; // b变为6 // 示例2:参与表达式运算 int x = 10; int y = x++; // y = 10(先赋值),然后x变为11 System.out.println("x=" + x + ", y=" + y); // 输出:x=11, y=10 int m = 10; int n = ++m; // m先变为11,然后n=11(后赋值) System.out.println("m=" + m + ", n=" + n); // 输出:m=11, n=11 // 示例3:复杂表达式 int i = 3; int j = (i++) * 2 + (++i); // 计算步骤: // 1. (i++) → 返回3(i变为4) // 2. (++i) → i先自增到5,返回5 // 3. j = 3*2 + 5 = 11 System.out.println("i=" + i + ", j=" + j); // 输出:i=5, j=11 ``` #### 3. **关键特性** - **左值问题**:在Java中,`i++`不能作为左值(不能赋值),而`++i`可以(在C++中,Java不允许)[^3][^4]: ```java int k = 5; // ++k = 10; // 在C++中合法,但在Java中编译报错 // k++ = 10; // 所有语言均非法 ``` - **效率差异**:`++i`比`i++`效率略高,因`i++`需临时变量存储原始值[^2]: ```java // 推荐循环写法(效率更优) for (int i = 0; i < 10; ++i) { ... } ``` #### 4. **边界情况(整数溢出)** 当`i`为`Integer.MAX_VALUE`(2147483647)时,`i++`会导致溢出[^5]: ```java int max = Integer.MAX_VALUE; System.out.println(max + 1 < max); // 输出true(溢出为负数) // 输出:存在(i+1)<i的情况,此时i为2147483647,i+1为-2147483648 ``` #### 5. **总结对比** | 操作符 | 返回值 | 自增时机 | 是否可作左值 | 典型场景 | |--------|-------------|--------------|--------------|------------------| | `i++` | **原始值** | **后自增** | ✗ | 需保留原始值时 | | `++i` | **自增后值**| **前自增** | ✓ (仅C++支持)| 循环迭代等高效场景 | > 提示:在`for`循环中两者效果相同,但建议用`++i`避免不必要的临时变量开销。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值