看到一个题目,大概是i=i++之类。
乍一看很简单,都知道i++的先参与计算再自增,
所以i不变。
但是仔细一想,
如果i不变,
那么在赋值之后,
自增的i,
增加的是谁呢?
逻辑顺序是怎样的呢?
//1.i=i++是这样的吗?; int i=0,temp;//此处temp代表副本 i=0; temp=i+1;//根据返回的值仍然为0判断,副本自增长,过了作用域,被GC回收了。 //2.还是这样的? i=0; i/*(此时i=1)*/=0/*(在执行i++过程中,改变了i的值,i=i+1,然而,i++返回运算前的副本,所以之前的自增被覆盖掉了)*/;
查看了相关的文章关于i++的底层实现原理
其中i=i++的描述是这样的
_temp = i; i = i + 1; i = _temp;
符合第二种猜想。
仔细想想,
使用i++时,
会直接影响i的值,
所以不太可能对副本进行自增。
i++的逻辑顺序应该是获取i,复制i,对i进行自增,返回i的副本。
public int add(int i){ int temp=i; i=i+1; return temp; }
在查看这篇文章时,
看到了另外一篇基于C++自增的文章,
其中,有这样一段代码,
#include <iostream> using namespace std; int main() { int i = 100; i += (i++); cout << i << endl; i = 100; i += (++i); cout << i << endl; return 0; }
输出结果为:201
202
原因大概是因为自增时,i的值被改变了。
开始也没多想,
只是试着去java中运行一下,
心里理所当然的认为结果应该是一致的。
public class ForTest { public int add(int i){ int temp=i; i=i+1; return temp; } public static void main(String[] args) { int i=100; /* * i=i+(i++); * i(100)=100+(i++(100)); * */ i+=(i++); System.out.println(i); i=100; i+=(++i); System.out.println(i); i=100; /* 前一个i++返回i自增前的值,但是i的值被改变,i=101. * 后一个i++也返回自增前的值,但是i此时的值已经是101, * 所以返回101,其后i自增为102. * 最后运算并赋值 * i=100+101; * tips:括号不影响i++的优先级,仍然先参与计算,再进行赋值; * */ i=(i++)+(i++); System.out.println(i); } }
结果是:200
201
201
疑问:为什么会不同?
思考:java和c++中,i的自增都是返回一个副本,
jvm是用c和c++编写的,底层机制应该相同
java的编译器是用java写的,编译的不同造成了不同结果。
c++中,i+=(++i)
i += 1; //100+1 = 101 i += i; //101+101 = 202
java中,i+=(++i)
i(1)=100; i(2)=101; i(101)=100+101;
在c++中,运算时,直接从i相应的栈中取i,所以被改变的i马上被使用。
在java中,运算时,虽然i被改变了,但是仍然作用不到之前的i,即在运算时,从上向下,从左向右,翻译成字节码。
这又涉及到了所谓的编译型语言和解释型语言,
参考了虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩
时间: 2024-11-29 03:28:02