很经典的无聊问题之一。
int i=0;
i=i++;
结果i是多少?
这是一个经常被提及的问题,答案一直五花八门。
具体测试一下以说明问题:
代码1:
-
publicclassTest{
-
publicstaticvoidmain(String[]args){
-
inti=0;
- i=i++;
- System.out.println(i);
- }
- }
结果i依然是0.分析其反编译后的代码:
-
publicstaticvoidmain(java.lang.String[]);
- Code:
-
0:iconst_0 //0放到栈顶
-
1:istore_1 //把栈顶的值保存到局部变量1,也就是i中
-
2:iload_1 //把i的值放到栈顶,也就是说此时栈顶的值是0
-
3:iinc1,1 //注意这个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,也就是说局部变量1,即i此时为1了。
-
6:istore_1 //把栈顶的值(0)保存到局部变量1,也就是让i为0了,所以最后i为0
-
7:getstatic#2;
-
10:iload_1
-
11:invokevirtual#3;
-
14:return
-
值得注意到是i被修改了两次,第一次是i++;i变为1,最后一次是i=0;所以结果i是0
代码2:
-
publicclassTest2{
-
publicstaticvoidmain(String[]args){
-
inti=0;
-
intj=0;
- j=i++;
- System.out.println(i);
- System.out.println(j);
- }
- }
这个结果肯定都知道,i是1,j是0.同样看反编译之后的代码:
-
publicstaticvoidmain(java.lang.String[]);
- Code:
-
0:iconst_0
-
1:istore_1 //i=0
-
2:iconst_0
-
3:istore_2 //j=0
-
4:iload_1 //把i的值放到栈顶,也就是说此时栈顶的值是0
-
5:iinc1,1 //局部变量1加1,也就是让i++了,此时i已经是1了,上面说过,此指令不会导致栈变化
-
8:istore_2 //把栈顶的值(注意是0)存入局部变量2,也就是j中,所以j=0
-
9:getstatic#2;
-
12:iload_1
-
13:invokevirtual#3;
-
16:getstatic#2;
-
19:iload_2
-
20:invokevirtual#3;
-
23:return
很明显可以看出,java是先把i的值取出来放到栈顶,我们可以认为是引入了第三个变量int k=i;然后i++,这时候i为1了,然后让j=k;也就是0.结论,i的++运算是在对j这个变量的赋值之前完成的。
代码3:
-
publicclassTest3{
-
publicstaticvoidmain(String[]args){
-
inti=0;
-
intj=0;
- j=++i;
- System.out.println(i);
- System.out.println(j);
- }
- }
结果大家也都知道,i=1,j=1
看操作过程:
-
publicstaticvoidmain(java.lang.String[]);
- Code:
-
0:iconst_0
-
1:istore_1 //i=0
-
2:iconst_0
-
3:istore_2 //j=0
-
4:iinc1,1 //局部变量i加1,这时候i变成1了 。
-
7:iload_1 //把i的值放到栈顶,栈顶的值是1
-
8:istore_2 //j=1
-
9:getstatic#2;
-
12:iload_1
-
13:invokevirtual#3;
-
16:getstatic#2;
-
19:iload_2
-
20:invokevirtual#3;
-
23:return
对比代码2和代码3,关键的差别就是iload_1 个iinc这两条指令的位置变了。
最后把iinc指令介绍一下:
iinc
Operation
Increment local variable by constant 给局部变量加上一个常量的值
Format
Forms
iinc = 132 (0x84)
Operand Stack
No change 操作数栈无变化
Description
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.
Notes
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.
很多人喜欢拿这个问题和C,C++中的情形来对比。其实在C/C++中这个问题是无任何意义的(当然,在java中也没有什么意义),因为C/C++的标准里并没有规定具体该怎么处理这类表达式,所以不同的编译器有不同的编译结果,而java语言规范却详细规定了表达式的提取规则,不会出现依赖于编译器的问题(假设所有java编译器都遵守规范)。
分享到:
相关推荐
Java循环的一个小问题,java中for(int i= 0; i<=10;i=i++)System.out.print(i);为什么无限输出0
这是和JVM的内存分配有关,JVM在处理这段带代码时,会先把i++的结果赋值给一个临时变量temp,然后再将这个临时变量的值赋值给i。即如下: int i = 0; int temp; // i = i++; int a = temp = i++;// 临时变量...
Java中 i = i++; 代码分析
if (i>=j) return i; else return j; } int main(void){ //定义main()函数 cout输入i,j:"; //显示提示信息 int i, j; //说明变量 cin>>i>>j; //从键盘上输入变量的值 cout最大数是:...
对于含有n个内节点的二元树,证明E=I+2n。其中E、I分别为外部和内部路径长度。
1、++i 的用法(以 a=++i ,i=2 为例) 先将 i 值加 1 (也就是 i=i+1 ),然后赋给变量 a (也就是 a=i ), ... 所以 a=i++ 相当于 a=i , i=i+1 3、++i 与 i++ a=++i 相当于 i++ , a=i a=i++ 相当于 a=i , i++ 4、++i
通过反编译出java虚拟机指令来看执行i=i++时内存中到底做了什么了?
java代码-i=3; a=i++; i+=a; \u6c42i=
字数转数灵感来自整个“态度 = A + T + T + I + T + U + D + E = 1 + 20 + 20 + 9 + 20 + 21 + 4 + 5 = 100%”的废话。
++i,i++,--i,i--终结-----即为对++i等的认识和难题的求解,如int j=++i+(++i)+(++i)+(++i);
i++) for (j=1;j<=i;j++) x++; 参考答案: i为1时,j值只能取1,语句执行1次; i为2时,j可取1或2,语句执行2次; …… i为n时,j可取1,2,…,n,语句执行n次。 语句频度=1+2+…+n=。 i=0; j=1; while (i+j<=n){ x++;...
6、 设<表达式>为E,<项>为T,<因子>为F,注:推导过程不能省略,以下均为最左推导 (1) E => T => F => i (4) E => E+T => T+T => T*F+T => ...(6) E => E+T => T+T => F+T => i+T => i+T*F => i+F*F => i+i*F => i+i*I
这是一本关于I++DME规范的详细介绍,里面定义了对象模型、类、操作方法等
浅谈 c i++ 与java i++的区别 c 代码: #include void main(){ int i=0;
数据结构矩阵相乘描述 M是m1*n1矩阵,N是m2*n2矩阵。当n1=m2时有: for(i=1;i<=m1;++i) for(j=1;j<=n2;++j){ Q[i][j]=0; for(k=1;k<=n1;++k)Q[i][j]+=M[i][k]*N[k][j]; }
尺寸测量标准,尺寸测量接口协议,I++DME,三坐标测量领域
i++){ if(i%4==0&&i0!=0||i%400==0){ sum+=366; }else{ sum+=365; } } for(int i=1;i;i++){ if(i==2){ if(year%4==0&&year0!=0||year%400==0){ sum+=29; }else{ sum+=28;...