i = i++;
来源:互联网 发布:网络理财软件排行榜 编辑:程序博客网 时间:2024/05/16 18:08
public class Test {
public static void main(String[] args) {
int i = 1;
i = i++;
System.out.println(i);
}
}
public static void main(String[] args) {
int i = 1;
i = i++;
System.out.println(i);
}
}
先想一想,这个程序会输出什么?是1还是2?按照我最初的想法,输出应该是2,因为把i赋值给i相当于没做什么操作,然后对i进行自加操作,所以变量i的值变为2了。但实际输出结果却是1!
跟David讨论了一下,他说这个i = i++;的操作可能相当于以下三步操作:①把变量i的值取出来,放在一个临时变量里(我们先记作temp);②把变量i的值进行自加操作;③把临时变量temp的值作为自增运算前i的值使用,在本题中就是给变量i赋值。因此,经过以上三步操作以后,虽然变量i在第②步操作中进行了自增运算,但第三步操作以后又把原来的值赋给了它,故最后输出结果为1。虽然我不确定这种解释是否正确,毕竟对底层实现细节不是太了解,但这种解释至少跟结果是符合的。
有的Java书上说放在变量后面的自增运算相当于两步操作,比如
f(i++);
就相当于
f(i);
i++;
但上面的例子比较特殊,用这种说法来解释就不太合适了,因为根据输出结果来看,
i = i++;
的情况就不能等同于
i = i;
i++;
看来,程序的简单和易读有的时候还确实是一个矛盾。
利用字节码解决java中遇到的问题(转载)
i=0;i=i++为什么等于0这个问题困扰了我好长的一段时间,结果前段时间还试图从虚拟机那个层面进行解释,但无论是线程还是方法调用都不能解释其现象,发现方向性错误,这只是一个语言的特性而已。在java lang spec中提到:
1、java运算符的优先级++符是大于=的。
2、The result of the postfix increment expression is not a variable, but a value.后++符表达式的结果是个值而不是一个变量。
也就是说后++符先将自己的值存储起来,然后对变量进行++;
再进行赋值操作,也就是将先存储起来的值赋给变量i,这样的操作就导致了i值被置为0了
1、java运算符的优先级++符是大于=的。
2、The result of the postfix increment expression is not a variable, but a value.后++符表达式的结果是个值而不是一个变量。
也就是说后++符先将自己的值存储起来,然后对变量进行++;
再进行赋值操作,也就是将先存储起来的值赋给变量i,这样的操作就导致了i值被置为0了
对于C和C++来说不一样,在讲到m=i++操作时,C语言是先将i的值赋给了m,然后将i值++,这样i=i++的结果自然就是1了,C的实现中是不存在那个中间的值的存储的。
由于java和c不同的语言特性,导致了i=i++的不同之处,前面的笔记中已经提到,由于java lang spec中的一些细微规定,导致其运行结果的不同,我们可以用个例子来看i=i++在jvm中实际的运行过程。
源程序test.java:
public class test {
public test() {
}
public static void main(String[] args) {
int i=0;
i=i++;
}
}
public test() {
}
public static void main(String[] args) {
int i=0;
i=i++;
}
}
我们用javap来看其实际的虚拟机指令集:
C:JBuilderXjdk1.4bin>javap -c -classpath "d:/" test
Compiled from "test.java"
Compiled from "test.java"
public class test extends java.lang.Object{
public test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: nop
5: return
public static void main(java.lang.String[]);
Code:
0: iconst_0 //常数0入栈
1: istore_1 //i赋值,常数值出栈
//至此完成i=0;
2: iload_1 //装载变量i,0入栈
//第2步是特殊的一步,这步将i值先行保存,以备赋值使用
3: iinc 1, 1 //变量值增加,栈内值不变
//至此完成i++
6: istore_1 //i赋值,0出栈。
//至此完成i=i++
7: nop //donothing
8: return
}
public test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: nop
5: return
public static void main(java.lang.String[]);
Code:
0: iconst_0 //常数0入栈
1: istore_1 //i赋值,常数值出栈
//至此完成i=0;
2: iload_1 //装载变量i,0入栈
//第2步是特殊的一步,这步将i值先行保存,以备赋值使用
3: iinc 1, 1 //变量值增加,栈内值不变
//至此完成i++
6: istore_1 //i赋值,0出栈。
//至此完成i=i++
7: nop //donothing
8: return
}
对比而言,对于i++而言,i=i++指令多了两步,2和6
其实这两步是赋值符号引起的,有意思的是第二步出现的时机,是在iinc之前,这就是因为java lang spec中规定的。
阅读全文
0 0
- 大话 i++、++i和i=++i、i=i++
- k=(++i)+(++i)+(++i)
- i = i++;i=++i
- i=i++; i=++i
- ++i *=i与 i++*= i
- 关于i++;++i;以及i=i++
- i++ ,++i,i=i++的问题
- i++ ,++i,i=i++的问题
- i++,++i,i=i+1 分析
- i = i++;
- a[i] = i++;
- I=I++
- i = i++;????
- 解释:i=i++
- i = &i
- i++ ++i区别 +=
- java i=i++
- i=i++分析
- 对 Linux 新手非常有用的 20 个命令
- Cgroups
- angularJs单向/双向数据绑定
- Struts2模型驱动原理
- Java获取用户ip
- i = i++;
- 自定义倒计时View的性能优化
- Ubuntu 16.10安装搜狗输入法并启用
- MATLAB入门教程
- 【AngularJS】自定义方法
- 初识Qt,几种写界面的方法
- 理解线程/多线程处理数组(MultiThreaded dealing with arrays)
- NOSQL2-MongoDB和Redis区别
- java算法【直接插入排序】