转载 Java i=i++问题

本文通过三个示例代码详细解析了Java中i++与++i的运算顺序及结果,揭示了它们在变量赋值前后的不同表现。

i++ ,++i,i=i++的问题


   int i=0;

      i=i++;

      结果i是多少?

      这是一个经常被提及的问题,答案一直五花八门。

      具体测试一下以说明问题:

      代码1:

  1. public class Test{
  2.     public static void main(String[] args){
  3.          int i=0;
  4.           i=i++;
  5.           System.out.println(i);
  6.      }
  7. }


     结果i依然是0.分析其反编译后的代码:

  1. public static void main(java.lang.String[]);
  2.    Code:
  3.    0:    iconst_0     //0放到栈顶
  4.    1:    istore_1    //把栈顶的值保存到局部变量1,也就是i中
  5.    2:    iload_1     //把i的值放到栈顶,也就是说此时栈顶的值是0
  6.    3:    iinc    1, 1 //注意这个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,也就是说局部变量1,即i此时为1了。
  7.    6:    istore_1     //把栈顶的值(0)保存到局部变量1,也就是让i为0了,所以最后i为0
  8.    7:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
  9.    10:   iload_1
  10.    11:   invokevirtual    #3; //Method java/io/PrintStream.println:(I)V
  11.    14:  return


值得注意到是i被修改了两次,第一次是i++;i变为1,最后一次是i=0;所以结果i是0

代码2:

  1. public class Test2{
  2.     public static void main(String[] args){
  3.          int i=0;
  4.          int j=0;
  5.           j=i++;
  6.           System.out.println(i);
  7.           System.out.println(j);
  8.      }
  9. }


这个结果肯定都知道,i是1,j是0.同样看反编译之后的代码:

  1. public static void main(java.lang.String[]);
  2.    Code:
  3.    0:    iconst_0
  4.    1:    istore_1     //i=0
  5.    2:    iconst_0
  6.    3:    istore_2     //j=0
  7.    4:    iload_1      //把i的值放到栈顶,也就是说此时栈顶的值是0
  8.    5:    iinc    1, 1 //局部变量1加1,也就是让i++了,此时i已经是1了,上面说过,此指令不会导致栈变化
  9.    8:    istore_2     //把栈顶的值(注意是0)存入局部变量2,也就是j中,所以j=0
  10.    9:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
  11.    12:   iload_1
  12.    13:   invokevirtual    #3; //Method java/io/PrintStream.println:(I)V
  13.    16:   getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
  14.    19:   iload_2
  15.    20:   invokevirtual    #3; //Method java/io/PrintStream.println:(I)V
  16.    23:  return

很明显可以看出,java是先把i的值取出来放到栈顶,我们可以认为是引入了第三个变量int k=i;然后i++,这时候i为1了,然后让j=k;也就是0.结论,i的++运算是在对j这个变量的赋值之前完成的。

代码3:

  1. public class Test3{
  2.     public static void main(String[] args){
  3.          int i=0;
  4.          int j=0;
  5.           j=++i;
  6.           System.out.println(i);
  7.           System.out.println(j);
  8.      }
  9. }


结果大家也都知道,i=1,j=1

看操作过程:

  1. public static void main(java.lang.String[]);
  2.    Code:
  3.    0:    iconst_0   
  4.    1:    istore_1    //i=0
  5.    2:    iconst_0
  6.    3:    istore_2     //j=0
  7.    4:    iinc    1, 1   //局部变量i加1,这时候i变成1了 。
  8.    7:    iload_1     //把i的值放到栈顶,栈顶的值是1
  9.    8:    istore_2    //j=1
  10.    9:    getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
  11.    12:   iload_1
  12.    13:   invokevirtual    #3; //Method java/io/PrintStream.println:(I)V
  13.    16:   getstatic    #2; //Field java/lang/System.out:Ljava/io/PrintStream;
  14.    19:   iload_2
  15.    20:   invokevirtual    #3; //Method java/io/PrintStream.println:(I)V
  16.    23:  return

对比代码2和代码3,关键的差别就是iload_1   个iinc这两条指令的位置变了。

    最后把iinc指令介绍一下:

iinc

Operation

Forms

Operand Stack

Description


The iinc opcode can be used in conjunction with the wide instruction to access a local variable using a two-byte unsigned index and to increment it by a two-byte immediate value.

Notes

Increment local variable by constant 给局部变量加上一个常量的值


Format

iinc
index
const


iinc = 132 (0x84)No change   操作数栈无变化

The index is an unsigned byte that must be an index into the local variable array of the current frame(§3.6). The const is an immediate signed byte. The local variable at index must contain an

int

. The value const is first sign-extended to an

int

, and then the local variable at index is incremented by that amount.


原文地址http://piaoboqiu.blog.163.com/blog/static/123127827200910192122472/

 

### Java实现100以内质数计算的代码解析 #### 质数定义 质数是指大于1的自然数中,除了1和它本身以外不再有其他因数的数。因此,在编程中判断某个数是否为质数的核心逻辑在于验证该数是否存在除1和其自身外的因子。 --- #### 代码结构分析 以下是基于引用中的代码实现[^3]: ```java public static void main(String args[]) { int i, j; for (i = 2; i <= 100; i++) { // 遍历从2到100的所有整数 for (j = 2; j <= i / 2; j++) { // 判断当前数是否有因子 if (i % j == 0) { // 如果存在因子,则不是质数 break; } } if (j > i / 2) { // 若循环未被中断,则说明无因子 System.out.println(i + "是素数!"); } } } ``` --- #### 关键点解析 1. **外部循环`for(i = 2; i <= 100; i++)`:** 外层循环用于遍历从2到100之间的每一个整数。这是因为小于2的数不可能是质数。 2. **内部循环`for(j = 2; j <= i / 2; j++)`:** 内部循环的作用是对当前数`i`进行因子检测。如果`i`能够被任何一个小于等于`i/2`的数整除,则表明`i`不是一个质数。 - `i/j >= 2` 的情况下,只需要检查到`i/2`即可,因为更大的因子必然对应更小的因子已经存在于前面的范围内[^4]。 3. **条件判断`if (i % j == 0)`**: 这一语句用来测试`i`能否被`j`整除。如果可以,则立即退出内层循环并跳过后续操作。 4. **最终判定`if (j > i / 2)`**: 当内层循环完成而没有发现任何因子时,变量`j`会超过`i/2`。此时可确认`i`是一个质数,并将其输出。 --- #### 性能优化建议 虽然上述算法功能正确,但在效率上仍有改进空间。例如可以通过减少不必要的迭代次数来提升性能。具体做法如下: - 将内层循环上限改为`Math.sqrt(i)`而不是`i/2`,这样可以显著降低时间复杂度[^2]。 修改后的版本如下所示: ```java public class PrimeNumbersOptimized { public static void main(String[] args) { int count = 0; for (int i = 2; i <= 100; i++) { boolean isPrime = true; for (int j = 2; j * j <= i; j++) { // 只需检查至sqrt(i) if (i % j == 0) { isPrime = false; break; } } if (isPrime) { System.out.println(i); count++; } } System.out.println("总共有" + count + "个质数"); } } ``` 此版本利用平方根特性减少了冗余运算,从而提高了执行速度。 --- #### 应用场景扩展 寻找特定区间内的所有质数不仅是一项基础练习题,还广泛应用于实际领域之中,比如加密技术、数据压缩以及随机数生成等方面。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值