初学Java,经常看到i++和++i的一些问题,在此整理一下。

首先看下面一个小程序:

  1. public class atest{
  2.  
  3. public static void main(String args[]){
  4. int s=1,m=1,n=1,p=1;
  5. s++;
  6. ++m;
  7. n=n++;
  8. p=++p;
  9. System.out.println("s="+s+"; m="+m+"; n="+n+"; p="+p);
  10. }
  11. }

输出为s=2; m=2; n=1; p=2

这里比较难以理解的应该是n的值,下面我们对程序进行反编译进行分析:

E:\test>javap -c atest
Compiled from "atest.java"
public class atest {
public atest();
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_1
1: istore_1
2: iconst_1
3: istore_2
4: iconst_1
5: istore_3
6: iconst_1
7: istore 4
9: iinc 1, 1
12: iinc 2, 1
15: iload_3
16: iinc 3, 1
19: istore_3
20: iinc 4, 1
23: iload 4
25: istore 4
27: getstatic #2 // Field java/lang/System.out:Ljava/
io/PrintStream;
30: new #3 // class java/lang/StringBuilder
33: dup
34: invokespecial #4 // Method java/lang/StringBuilder."<
init>":()V
37: ldc #5 // String s=
39: invokevirtual #6 // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
42: iload_1
43: invokevirtual #7 // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
46: ldc #8 // String ; m=
48: invokevirtual #6 // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
51: iload_2
52: invokevirtual #7 // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
55: ldc #9 // String ; n=
57: invokevirtual #6 // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
60: iload_3
61: invokevirtual #7 // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
64: ldc #10 // String ; p=
66: invokevirtual #6 // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
69: iload 4
71: invokevirtual #7 // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
74: invokevirtual #11 // Method java/lang/StringBuilder.to
String:()Ljava/lang/String;
77: invokevirtual #12 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
80: return
}

对相关部分进行分析,注释如下:

0: iconst_1                       //把1放到栈顶
1: istore_1                       //把栈顶的值放到局部变量1中,即s
2: iconst_1                       //把1放到栈顶
3: istore_2                       //把栈顶的值放到局部变量2中,即m
4: iconst_1                       //把1放到栈顶
5: istore_3                       //把栈顶的值放到局部变量3中,即n
6: iconst_1                       //把1放到栈顶
7: istore 4                        //把栈顶的值放到局部变量4中,即p
9: iinc 1, 1                       //把局部变量1(也就是s),增加1,这个指令不会导致栈的变化,s此时变成2
12: iinc 2, 1                     //把局部变量2(也就是m),增加1,这个指令不会导致栈的变化,m此时变成2
15: iload_3                      //把局部变量3(也就是n)的值放到栈顶,此时栈顶为1
16: iinc 3, 1                     //把局部变量3(也就是n),增加1
19: istore_3                     //把栈顶的值放到局部变量3(也就是n)中
20: iinc 4, 1                     //把局部变量4(也就是p),增加1
23: iload 4                       //把局部变量4(也就是p)的值放到栈顶,此时栈顶为2
25: istore 4                      //把栈顶的值放到局部变量4(也就是p)中

由此看见,i=i++是先将i的值放到栈顶,而后对i进行操作,最后返回给i的栈顶值还是先前的值,而i=++i是先对i进行操作,然后将i的值放到栈顶,最后返回给i的栈顶值也就是计算后的值。

扩展练习:

  1. public class atest{
  2.  
  3. public static void main(String args[]){
  4. int s=0,m=0,n=0,p=0;
  5. for(int i=0;i<100;i++){
  6. s++;
  7. ++m;
  8. n=n++;
  9. p=++p;
  10. }
  11. System.out.println("s="+s+"; m="+m+"; n="+n+"; p="+p);
  12. }
  13. }

随机推荐

  1. Mybitis配置文件中的别名以及mapper中的namespace

    1 基本知识 MyBatis中如果每次配置类名都要写全称也太不友好了,我们可以通过在主配置文件中配置别名,就不再需要指定完整的包名了. 别名的基本用法: <configuration> & ...

  2. app中rem算法

    第一次用vue做APP被rem坑惨了 下面贴出 rem 的算法及使用方法 在自定义js中定义函数 export default { install: function(Vue, options) { ...

  3. JS组件系列——在ABP中封装BootstrapTable

    前言:关于ABP框架,博主关注差不多有两年了吧,一直迟迟没有尝试.一方面博主觉得像这种复杂的开发框架肯定有它的过人之处,系统的稳定性和健壮性比一般的开源框架肯定强很多,可是另一方面每每想到它繁琐的封装 ...

  4. css3关键帧动画实现轮播效果

    实现效果:打开手机京东,可以看到首页的头部,以这个头部为基础,仿写一个类似的样式. 思路:仔细观察可以发现,手机京东的头部是以一个搜索栏和轮播特效组成的,而这个搜索栏是以轮播特效做为背景的,现在运用c ...

  5. iOS源码博文集锦3

    iOS精选源码 高仿淘宝首页 登录动画 iOS高德二次封装,有定位,轨迹,语音实时导航,GPS纠偏..... 逗视iOS客户端MGDS_Swift 两句代码搞定转场动画 自定义刷新控件 已封装支持自定 ...

  6. oracle 通过同义词建立视图

    需要给予以下权限. GRANT CREATE VIEW TO tms;GRANT SELECT ANY table TO tms;GRANT SELECT ANY DICTIONARY TO tms;

  7. Linux Shell 1 - Print from terminal

    Two ways to print info from terminal - echo & printf - Echo a. Exclamation mark is supported in ...

  8. 为什么要学习Java EE

    Java EE学习之路 学习了Java SE,还只是完成“万里长征”的第一步. 接下来选择学习Java EE或是Java ME(或者你还想不断深入学习Java SE,只要你喜欢,你可以一直深入下去,就 ...

  9. MapReduce编程之Reduce Join多种应用场景与使用

    在关系型数据库中 Join 是非常常见的操作,各种优化手段已经到了极致.在海量数据的环境下,不可避免的也会碰到这种类型的需求, 例如在数据分析时需要连接从不同的数据源中获取到数据.不同于传统的单机模式 ...

  10. [算法题] Two Sum

    题目内容 题目来源:LeetCode Given an array of integers, return indices of the two numbers such that they add ...