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

首先看下面一个小程序:

public class atest{

    public static void main(String args[]){
int s=1,m=1,n=1,p=1;
s++;
++m;
n=n++;
p=++p;
System.out.println("s="+s+"; m="+m+"; n="+n+"; p="+p);
}
}

输出为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的栈顶值也就是计算后的值。

扩展练习:

public class atest{

    public static void main(String args[]){
int s=0,m=0,n=0,p=0;
for(int i=0;i<100;i++){
s++;
++m;
n=n++;
p=++p;
}
System.out.println("s="+s+"; m="+m+"; n="+n+"; p="+p);
}
}

随机推荐

  1. MVC 路由设置伪静态

    public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/ ...

  2. [COGS 2051] 王者之剑

    Saber大法吼 2051. 王者之剑 ★★★☆   输入文件:Excalibur.in   输出文件:Excalibur.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述 ...

  3. RabbitMQ入门-从HelloWorld开始

    从读者的反馈谈RabbitMQ 昨天发完<RabbitMQ入门-初识RabbitMQ>,我陆陆续续收到一些反馈.鉴于部分读者希望结合实例来讲 期待下篇详细,最好结合案例.谢谢! 哪都好,唯 ...

  4. ASP.NET MVC 开发微信支付H5(外置浏览器支付)

    H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付. 主要用于触屏版的手机浏览器请求微信支付的场景.可以方便的从外部浏览器 ...

  5. 44. leetcode 28. Implement strStr()

    28. Implement strStr() Implement strStr(). Returns the index of the first occurrence of needle in ha ...

  6. Android Studio设置快捷键和背景

    1.快捷键设置 复制代码并且向下移动 向下移动代码 代码提示 代码改错 更改文件名称   alt + shift + R   2.更改背景颜色-豆绿色           来自为知笔记(Wiz)

  7. CentOS6 安装Sendmail + Dovecot + Squirrelmail

    本文记录在本地虚拟机CentOS6上搭建Sendmail + Dovecot + Squirrelmail 的Webmail环境的过程,仅仅是本地局域网的环境测试,不配置DNS, 也没有安全认证,Sq ...

  8. <Mastering KVM Virtualization>:第三章 搭建独立的KVM虚拟化

    在第二章,你了解了KVM的内部结构:在本章中,您将了解如何将Linux服务器设置为虚拟化主机.我们正在讨论将KVM用于虚拟化并将libvirt作为虚拟化管理引擎. KVM开启了虚拟化并利用你的服务器或 ...

  9. Webservice 中涉及的几个概念

    开发webservice有一段时间了.但是对其中的协议及实现一直存在疑惑.这里搜集相关概念.用以更好的理解它. 一.什么是Webservice WebService是一种跨编程语言和跨操作系统平台的远 ...

  10. 分辨率验证工具 - 【Firesizer】的使用升级-Firefox-29.0

    今天打算使用Firesizer,但是在Firefox浏览器的右下角找不到Firesizer了. 在官网搜了搜(https://addons.mozilla.org/en-US/firefox/addo ...