zoukankan      html  css  js  c++  java
  • JAVA 连等赋值问题

    一、描述

    关于 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,如图:

    连等赋值1

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

    连等赋值2

    所以最终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 中一定是能找到更为准确的答案的,如果你有兴趣可以自行查阅;

  • 相关阅读:
    Moq4在.NET3.5和.NET4版本之间的差异
    TDD中的迭代
    洛谷 3413 萌数
    割点(tarjan)
    hdu-4507 吉哥系列故事——恨7不成妻
    hdu-3709 Balanced Number
    poj-3252 Round Numbers
    hdu 1007 Quoit Design 分治求最近点对
    LA 3905 Meteor 扫描线
    uva 11464
  • 原文地址:https://www.cnblogs.com/sanzao/p/10278070.html
Copyright © 2011-2022 走看看