关于Java的=赋值操作和方法传递对象时的引用
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11405920.html
下面通过一段代码和debug结果来展示Java中=操作的赋值改变过程。Test实体类会在最后贴出。
Test test1 = new Test();
test1.setKey(1);
test1.setValue(1);
Test test4 = new Test();
test4.setKey(4);
test4.setValue(4);
Test test2 = test1;
test2.setIndex(2);
test2 = test4;
test2.setIndex(4);
结果:

可以看出:Java的=操作符会将=右侧对象实例的地址引用赋值给=左侧的对象实例,在被赋值期间,值的改变是怎样的呢?
继续看:

可以看到test1的index值是改变了的,test4的index值也是改变了的,test2首先是test1的引用,在引用test1的时候改变test2的值,test1的值也会相应改变,说明在引用期间所有的改变都是针对实际内存地址操作的,而不是单纯针对该对象的值进行改变。
接下来,我们再看一下方法传递时候的引用是怎么改变的:
先贴上两个传入test参数并且在方法内尝试改变index值的方法:
/**
* 尝试直接改变test的index值
* @param test
*/
public static void tryInChangeIndex(Test test){
test.setIndex(123);
} /**
* 尝试间接改变test的index值
* @param test
*/
public static void tryLinkChangeIndex(Test test){
Test testLink = new Test();
testLink = test;
testLink.setIndex(456);
}
结果:

毫无疑问,成功改变test1的值。
再看下一个方法:

同样可以改变,没有问题。
再看看String传递是怎么回事;
先贴尝试改变String的两个方法:
/**
* 尝试改变string的值
* @param str
*/
public static void tryChangeString(String str){
str = "hello new str value";
} /**
* 尝试改变string的值方法2
* @param str
*/
public static void tryChangeStringTwo(String str){
String newStr = str;
newStr = "world in this place";
}
String str1 = "good nice";
String str2 = "i'm iron man";
tryChangeString(str1);
tryChangeStringTwo(str2);
debug结果:


从这里可以看出,方法里面的str值是有改变的,但是方法外str1的值依然是“good nice”,这说明传入的String 类型是不能被改变的。
继续看下面这个方法:

同样的,在方法里面,虽然把str指向了newStr,并且给newStr赋了新的值,但是str的值依然是没有变化的,我们再看一下str2的值:

str2的值也是没有被改变。
我猜测: 这是因为参数方法在参数列表这里的String str 重新创建了一个实例,而且将该实例的内存引用地址指向了str2的内存引用地址,所以值会相等,但是当对str进行赋值操作的时候,会重新new String,也就是重新开辟一块内存空间去存放这个新的值,并且str会指向这块内存地址,所以改变str的值是无法改变str2的值的,因为它俩根本就不是同一个实例,只是指向了相同的内存引用地址而已.
*** String 是final类,不可被继承, 但是String如果实例化的时候没有定义为final变量,还是可以重新赋值的!编译器不会报错!注意区别 final类和final变量.
再来看一种情况:
TestFather father = new TestFather();
Test son = new Test();
son.setIndex(123456);
father.setSon(son);
son.setIndex(789);
这种情况下,father里面的son值会怎么变化?debug看一下

到了72行,72行还没执行的之后,father的son的index值还是123456的,再往下走一步:
BOOM!!! Every thing is diffrent

很明显,son变了,father拥有的只是son的一个引用,拥有了son的身体却没有son的灵魂,这里涉及到一个深拷贝和浅拷贝的问题,有兴趣可以自行Google或者Baidu。
Test.java文件
package entity; /**
* 测试实体类
*/
public class Test {
private int key;
private int value;
private int index; //getter setter 省略
}
TestFather.java
package entity; /**
* Test的father
*/
public class TestFather {
private int num;
private Test son; public int getNum() {
return num;
} public void setNum(int num) {
this.num = num;
} public Test getSon() {
return son;
} public void setSon(Test son) {
this.son = son;
}
}
结束
关于Java的=赋值操作和方法传递对象时的引用的更多相关文章
- java字符流操作flush()方法及其注意事项
java字符流操作flush()方法及其注意事项 flush()方法介绍 查阅文档可以发现,IO流中每一个类都实现了Closeable接口,它们进行资源操作之后都需要执行close()方法将流关闭 ...
- Java继承中属性、方法和对象的关系
大家都知道子类继承父类是类型的继承,包括属性和方法!如果子类和父类中的方法签名相同就叫覆盖!如果子类和父类的属性相同,父类就会隐藏自己的属性! 但是如果我用父类和子类所创建的引用指向子类所创建的对象, ...
- 【转】两道面试题,带你解析Java类加载机制(类初始化方法 和 对象初始化方法)
本文转自 https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html 关键语句 我们只知道有一个构造方法,但实际上Ja ...
- Java的参数传递是「值传递」还是「引用传递」?
关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题. 有人说Java中只有值传递,也有人说值传递和引用传递都是存在的,比较容易让人产生疑问. 关于值传递和引用传递其实需要分情况看待. ...
- spring mvc 处理pojo传递对象时该对象继承父类的属性在网络接收端接收该属性值总是null,why?
//=========================== 情形一: ===============================//在网络上传递User1类对象时info属性值在网络的另一端能够接 ...
- java 保护内存操作的方法
1.与c++不同,在java中,没有通过使用强制转换指针类型或者通过进行指针运算直接访问内存的方法.在java中使用对象时,需要严格地遵守类型规则.如果存在一个Mountain类对象的引用(类似于c+ ...
- java File文件操作共用方法整理
package org.jelly.util; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io ...
- form插件ajaxForm和ajaxSubmit方法传递对象参数说明
form插件的ajaxForm和ajaxSubmit方法的Options对象还可以用来将值传递给jQuery的$.ajax方法.如果你熟悉$.ajax所支持的options,你可以利用它们来将Opti ...
- Java 中如何使用clone()方法克隆对象?
java为什么要 对象克隆: 在程序开发时,有时可能会遇到以下情况:已经存在一个对象A,现在需要一个与A对象完全相同的B 对象,并对B 对象的属性值进行修改,但是A 对象原有的属性值不能改变.这时,如 ...
随机推荐
- Identity Server 4到今年年底就停止支持了,试一下使用Orchard Core 作为认证服务
Identity Server 4到今年年底就停止支持了,新的版本需要收费(好像目前是按企业规模,不过将来说不准).我们需要为这种情况做一些技术准备,至少需要为用户多准备一些可选方案.从目前成熟的开源 ...
- Flask_Flask-Mail邮件扩展(十三)
在开发过程中,很多应用程序都需要通过邮件提醒用户,Flask的扩展包Flask-Mail通过包装了Python内置的smtplib包,可以用在Flask程序中发送邮件. Flask-Mail连接到简单 ...
- mysql数据库忘记root密码怎么办?
mysql数据库忘记root密码怎么破解和修改 1.停止数据库的运行 [root@localhost ~]# /etc/init.d/mysqld stop 或者[root@localhost ~]# ...
- windows更改pip源(可用)
中国科学技术大学 : https://pypi.mirrors.ustc.edu.cn/simple 清华:https://pypi.tuna.tsinghua.edu.cn/simple 豆瓣:ht ...
- websocket 使用 spring 的service层 ,进而调用里面的 dao层 来操作数据库 ,包括redis、mysql等通用
1.前言 描述一下今天用websocket踩得坑 --->空指针异常! 我想在websocket里面使用service 层的接口,从中获取数据库的一些信息 , 使用 @Autowired 注 ...
- SQL高级优化(六)之MySQL索引
一.索引概述 1. 索引的优点 为什么要创建索引?这是因为,创建索引可以大大提高系统的查询性能.如果不使用索引,查询时从第一行开始查询.如果使用了索引,所以就可以更加快速的找到希望的数据. 第一. ...
- 大型站点TCP/IP协议优化
作为一个DAU上百万或千万的站点,不仅仅需要做好网站应用程序.数据库的优化,还应从TCP/IP协议层去进行相关的优化: 在我的工作中,曾使用到了以下的几种基本的优化方式: 增大最大连接数 在Linux ...
- BIO,NIO,AIO 总结
BIO,NIO,AIO 总结 一.同步阻塞 (BIO) 同步阻塞IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器就需要启动一个线程进行处理,如果这个连接不 做任何事情会造成不必要的线 ...
- Unity3D开发入门教程(四)——用Lua实现组件
五邑隐侠,本名关健昌,12年游戏生涯. 本教程以 Unity 3D + VS Code + C# + tolua 为例. 一.Lua组件基类 1.在 Assets/Lua 目录下新建com目录用于存放 ...
- 【Java】Super
Super super用于调用父类的属性.方法.构造器,与this相同. super的使用 属性与方法 在子类的方法或构造器中.通过使用"super.属性"或"super ...