一、描述

关于 Java 连等赋值,例如a=b=c;我们知道它是从右往左依次赋值的,其结果大致可以拆分为b=c;a=b;,但是当栈中没有持有变量的引用时,则会出现问题,例如:

public class Node {
int i;
Node n; Node(int i) {
this.i = i;
} Node(Node n, int i) {
this.i = i;
this.n = n;
} @Override
public String toString() {
return i + " ";
} public static void main(String[] args) {
Node nn = new Node(0);
Node n1 = new Node(nn, 1);
Node n2 = n1; n1.n = n1 = new Node(nn, 3);
System.out.println(n1.toString() + n1.n.toString());
System.out.println(n2.toString() + n2.n.toString());
}
} // 打印:
// n1:3 0
// n2:1 3

如果将以上n1.n = n1 = new Node(nn, 3);拆分后:

n1 = new Node(nn, 3);
n1.n = n1; // 打印:
// n1:3 3
// n2:1 0

二、分析

1. 初始情况

2. 拆分的赋值

  • 首先n1指向node3
  • 然后n1.n指向node3自身,形成闭环
  • 所以结果打印n1:3 3 ;n2:1 0 ,这里很容易理解

3. 连等赋值

在开始赋值的时候因为 stack 里面并没有持有n1.n的引用,所以会现在 stack 中创建一个临时变量指向n1.n,如图:

所以在连等赋值之后变为:

所以最终n1.n = n1 = new Node(nn, 3);会打印n1:3 0;n2:1 3

  • 因为在执行完n1 = new Node(nn, 3);之后,stack 中的n1.n仍然指向原n1中的node
  • 在执行n1.n = n1的时候,两个n1所指示的对象已经不再相同,所以会等到以上结果;

三、总结

  • 对于以上问题之所以会出乎意料,就是因为原本以为是原子性的步骤,实际上是分布完成的;

  • 类似的问题其实在 Virtual Machine Specifications 中一定是能找到更为准确的答案的,如果你有兴趣可以自行查阅;

JAVA 连等赋值问题的更多相关文章

  1. atitit.java给属性赋值方法总结and BeanUtils 1.6.1 .copyProperty的bug

    atitit.java给属性赋值方法总结and BeanUtils 1.6.1 .copyProperty的bug 1. core.setProperty(o, "materialId&qu ...

  2. Jsp获取Java的重定向赋值(String)

    Jsp获取Java的重定向赋值(String) Java代码片段: //传递String request.setAttribute("msg", msg); //重定向 reque ...

  3. java.sql.Date赋值给了java.util.Date.转化成JSONArray时出错net.sf.json.JSONException: java.lang.reflect.InvocationTargetException

    net.sf.json.JSONException: java.lang.reflect.InvocationTargetExceptionat net.sf.json.JSONObject.defa ...

  4. properties文件属性值@Value注解为 java entity属性赋值

    一.使用@Value为 java entity类中的非static属性赋值 举个栗子,一目了然 1.1 properties文件 1.2 servlet.xml 文件增加的配置: 1.2.1 serv ...

  5. java中的赋值

    java中的赋值使用符号“=”. 按照java编程思想的解释:它的意思是“取等号右边的值,把它复制给左边”. 当然左边必须是一个明确的,已命名的变量. 基本类型: int a=2; int b=3; ...

  6. atitit.java方法属性赋值and BeanUtils 1.6.1 .copyProperty的bug

    atitit.java分配给属性值方法and BeanUtils 1.6.1 .copyProperty的bug 1. core.setProperty(o, "materialId&quo ...

  7. JAVA学习笔记之JAVA 对象引用以及赋值

      关于对象与引用之间的一些基本概念. 初学Java时,在很长一段时间里,总觉得基本概念很模糊.后来才知道,在许多Java书中,把对象和对象的引用混为一谈.可是,如果我分不清对象与对象引用, 那实在没 ...

  8. JAVA变量初始化赋值null

     在Java中,null值表示引用不指向任何对象.运行过程中系统发现使用了这样一个引用时·可以立即停止进一步的访问,不会给系统带来任何危险. 1.如果是对象的field的话那么系统在初始化对象的时候会 ...

  9. java将一个List赋值给另一个List的4种方法

    编辑 删除 声明:ArrayList a, 仅仅只是声明了一个list变量,其未来作用相当于C++中的引用变量,亦或者相当于一个对象块的索引,但并未为其分配具体的完整的对象所需要的内存空间,其所分配的 ...

随机推荐

  1. Inmon和Kimball数仓建模思想

    Inmon和Kimball是数据仓库领域伟大的开拓者,他们均多年从事数据仓库的研究,Inmon还被称为“数据仓库之父”.Inmon的<数据仓库>和Kimball的<数据仓库工具箱&g ...

  2. 转 the best for wcf client

    原文:http://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-bl ...

  3. Linux系统如何添加IP别名

    IP别名可以在一块物理网卡上绑定多个IP地址,这样就能够在使用单一网卡的同一个服务器上运行多个基于IP的虚拟主机,简单来说,IP别名就是一张物理网卡上配置多个IP,实现类似子接口之类的功能. 那么IP ...

  4. macOS实现视频转音频以及音频拼接

    macOS实现视频转音频以及音频拼接 ffmpeg 的安装 终端输入以下指令: brew install ffmpeg 视频转音频 终端输入以下指令: ffmpeg -i 视频名称.flv -vn - ...

  5. 十八、泛型 l 注解 l Servlet3.0 l 动态代理 l 类加载器基础加强

    l 泛型 l 注解 l Servlet3.0 l 动态代理 l 类加载器 泛型 1 回顾泛型类 泛型类:具有一个或多个泛型变量的类被称之为泛型类. public class A<T> { ...

  6. [转]Setting Keystone v3 domains

    http://www.florentflament.com/blog/setting-keystone-v3-domains.html The Openstack Identity v3 API, p ...

  7. 【安富莱二代示波器教程】第16章 附件A---电阻屏触摸校准

    第16章      附件A---电阻屏触摸校准 二代示波器的触摸校准比较简单,随时随地都可以做触摸校准,按下K1按键即可校准.有时候我们做触摸校准界面,需要在特定的界面才可以进入触摸校准状态,非常繁琐 ...

  8. Oracle数据库备份及还原

    Oracle数据库备份 1:找到Oracle安装路径我的就是默认C盘  C:\app\wdjqc\admin\orcl\adump 2:执行文件:back.bat 文件内容如下: @echo off ...

  9. [Swift]LeetCode68. 文本左右对齐 | Text Justification

    Given an array of words and a width maxWidth, format the text such that each line has exactly maxWid ...

  10. springmvc 请求参数解析细节

    springmvc 的请求流程,相信大家已经很熟悉了,不熟悉的同学可以参考下资料! 有了整体流程的概念,是否对其中的实现细节就很清楚呢?我觉得不一定,比如:单是参数解析这块,就是个大学问呢? 首先,我 ...