i++ 和 i=i++和i=i+1和j=j++的细节问题

时间:2022-08-28 03:01:02

最近做了下搜狗的在线笔试,发现语言考的全是细节啊。后来反思我对语言的掌握,发现其实根基不牢靠。。。唉 不说了。打算再看书。
今日读到《java程序员面试宝典》一个问题

public static void main(String args[])
{

Inc inc= new Inc();
int i=0;
inc.fermin(i);
i=i++;
System.out.println(i);

}
void fermin(int i)
{
i++;
}
//摘自——page:33 from 《Java程序员面试宝典》

我是这么想的,首先 i=0,然后调用fermin函数。调用函数是值传递。虽然参数也是i,但是完全不是一会是。只是值的copy,那么0给fermin在里面遇到i++。那么i++执行完结果就是1,然后函数结束,但是void。值不返回。所以全局变量i还是0
接下来到i=i++;我认为是运算级别++高于=,那么先是执行右边,i++那么结果是1,然后i=1吧。
但是书里写的结果是0,我赶紧去编译器测试了下。发现确实是0

问题来了。
首先我想到 是不是因为Java里面是i++先是赋值给i。然后再加1,然后这个1丢掉了。
还是因为编译器在语法解析的差别。我去Dev-c++测试了C语言代码。发现也是0。

我记得以前教C老教授教的。大概是输出1才对啊。所以我一直理解是1。
**实际调研如下:
i=i++是如何处理的?**

  1. 先是读取右边的i的值0,然后存入一个临时内存。
  2. 然后相当于0++;是1
  3. 然后遇到赋值的时候,是把原来保存的临时内存给返回来。
  4. 也就是i=0而不是i=1。

那么i=i+1是如何呢?
1.右边,读取i的值,然后直接i+1,即0+1
2.然后i=右边=1

接下来是j=i++;

j=0;
i=1;
j=i++;//输出j是0,和i=i++输出的i一样

总结记忆:
++和–
1.单独作用于操作数,那就是加1或减1,前缀后缀都是。等价于i=i-1 i=i+1;
i++ ++i 都+1
i– –i 都-1

2.作用在操作数,且出现在表达式。那么问题就不一样了。
前缀++ – 都是进行加1和减1操作
左边=++i –i都是先对操作数处理之后参与
但是
后缀++ –都不变。还是原来的值。
左边=i++ i–都是先把原来的值copy保存。然后+1 -1参与运算。然后再把原值返回,之后i本身的值是不变的。


后续:
问题完了嘛?还没有

    int i=0;
int j=0;
j=i++;
System.out.println(i); //输出是0
i=0;
j=0;
j=i++ +1;
System.out.println(i); //i输出是1,为啥i++ +1之后i就是1了呢。我又不懂了,不应该也是i还是0嘛。

//类比下面代码
i=0;
j=0;
j=i++; //此时输出i=1 输出j=0,因为j= (i的原值0)。
i=i++; //此时最终打印结果i=0,起码这俩i应该是2个不同的内存空间啊,左边的i=0那没错。但是右边那个i按照上面的j=i++输出的i=1应该是1吧。。但是最后打印输出i是0,似乎是以左i的地址为主。我猜测这种情况就要看编译器怎么处理来了。具体我还不知道。

百度了下,没什么好的细节分析。
翻了《Java核心技术卷一》他区别了两种情况,但没讲原理。
翻了《thinking in java 》没有区别两种情况。
**但是这两本书都建议就是少在表达式里面用++。避免bug。
我也这么想的。能不用就不用,免得头疼。虽然性能高一丢丢,但是忽略不计的**