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. 初始情况

初始化

  1. 拆分的赋值

分步赋值

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

  1. 连等赋值

在开始赋值的时候因为 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所指示的对象已经不再相同,所以会等到以上结果; 欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 891219277

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

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

原文地址:http://blog.51cto.com/14084556/2345033

时间: 2024-11-25 15:44:44

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

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

atitit.java给属性赋值方法总结and BeanUtils 1.6.1 .copyProperty的bug 1. core.setProperty(o, "materialId", null); 1 2. Java Reflection (JAVA反射) 1 3. 反射的用处 2 4. Java类反射中所必须的类: 2 BeanUtils.copyProperty 2 5. BeanUtils.setProperty 2 6. 参考 4 1. core.setProperty(

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

Jsp获取Java的重定向赋值(String) Java代码片段: //传递String request.setAttribute("msg", msg); //重定向 request.getRequestDispatcher("error.jsp").forward(request, response); Jsp代码片段: <%@ page language="java" contentType="text/html; char

JAVA变量初始化赋值null

 在Java中,null值表示引用不指向任何对象.运行过程中系统发现使用了这样一个引用时·可以立即停止进一步的访问,不会给系统带来任何危险. 1.如果是对象的field的话那么系统在初始化对象的时候会把那些对象的值赋值为null,基本数据类型也有它们的初始值 2.如果是在方法内,那么程序员需要自己给这些变量赋值. class T{   Object obj = null;   Object obj1;//系统在初始化的时候会自动的给他赋值为null } class T{   public voi

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

atitit.java分配给属性值方法and BeanUtils 1.6.1 .copyProperty的bug 1. core.setProperty(o, "materialId", null); 1 2. Java Reflection (JAVA反射) 1 3. 反射的用处 2 4. Java类反射中所必须的类: 2 BeanUtils.copyProperty 2 5. BeanUtils.setProperty 2 6. 參考 4 1. core.setProperty(o

Java基础_赋值运算

* short s=1;s = s+1; 运算错误,提示损失精度.因为s+1为int类型,int类型赋值给short类型会损失精度 ps:精度变化由小到大为  byte->short->int->long ,反过来就会损失精度 * short s=1;s+=1; 结果为2. +=是一个赋值运算符.可以理解为 (short) s = (short) (s+x)

java中变量赋值的理解

1.当赋值的值超出声明变量的范围时候,会报错! byte a =200 //会报错,因超出范围. byte a =(byte)200;//进行一个强制转换,就不会报错,不过会超出范围,超出部分会从头开始加, 由于byte的范围为-128~127,所以是-128+73为所得结果.2.声明一个整数类型时候,默认都是int类型(4个8位):如果具体的数值比声明变量的取值范围小,则不报错. 例:short a =222;3.long l = 88888888888l 很明显,这一长串数字是好超过int的

java 对象引用与赋值

案例: package com.util; import java.util.ArrayList;import java.util.List; public class CopyObjectUtil {    private static List<String> list;    private static User userTemp;    static{        list=new ArrayList<String>();        list.add("a

JAVA位、赋值、条件运算符等

public class NewClass { public void 位运算符(){ /* * 1 ~ 按位取反 1=~0 * 2 & 按位与 0&1=0 1&1=1 0&0=0 * 3 | 按位或 0|1=1 1|1=1 0|0=0 * 4 ^ 按位异或 0^1=1 1^1=0 0^0=0 1^0=1 相同得0,相异得1 */ int x=53; int r=~x; System.out.println("r="+r); //-54,按位取反加一 i

Java:数组的赋值实际上是引用

1 public class ArrayOfPrimitives { 2 3 public static void main(String[]args){ 4 int[]a1={1,2,3,4,5}; 5 int[]a2; 6 a2=a1; 7 8 for(int i=0;i<a1.length;i++) 9 a2[i]+=1; 10 for(int i=0;i<a1.length;i++) 11 System.out.println(a1[i]); 12 } 13 } 输出 2 3 4 5