关于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 对象原有的属性值不能改变.这时,如 ...
随机推荐
- PIC18 bootloader之CAN bootloader
了解更多关于bootloader 的C语言实现,请加我Q扣: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). PIC18 ...
- .NET6 微服务——CI/CD(1):搭建Jenkins并实现自动构建
CI/CD 它的意思是 持续集成/持续部署,这也不是新概念.那些八股文就不写了,说话的方式简单点:如果成功搭建CI/CD环境,当你需要迭代线上程序时,只需通过git提交代码就可以,其他什么都不用做.是 ...
- 【】(Git)用动图展示10大Git命令
1.说明 git merge.git rebase.git reset.git revert.git fetch.git pull.git reflog-- 你知道这些 git 命令执行的究竟是什么任 ...
- ActiveMQ基础教程(四):.net core集成使用ActiveMQ消息队列
接上一篇:ActiveMQ基础教程(三):C#连接使用ActiveMQ消息队列 这里继续说下.net core集成使用ActiveMQ.因为代码比较多,所以放到gitee上:https://gitee ...
- python 字典 分别根据值或键进行排序的方法
最近经常遇到根据字母出现的频率进行排序的题目 我的思路一般是借用字典统计字母出现的频率 然后对字典按照值进行排序 但是每次按照值进行排序时 都会忘记排序方法 在此记录一下,以加深印象 字典原始值如下: ...
- 在 CentOS 7 上安装和配置 Puppet
1 准备 2台 centos7 (master/server:192.168.1.103 agent/client:192.168.1.106) 分别添加puppet自定义仓库 https://yum ...
- 【填坑往事】使用Rxjava2的distinct操作符处理自定义数据类型去重的问题
最近碰到一个问题,自定义数据类型列表中出现了重复数据,需要去重.处理去重的办法很多,比如借助Set集合类,使用双重循环拿每一个元素和其他元素对比等.这里介绍一种简单而且比较优雅的方式:使用Rxjava ...
- Word文档学习小练习链接
1. < Word2010初学> https://www.toutiao.com/i6487370439910752782/ 2. <Word2010格式化可爱的家乡> htt ...
- 微信小程序配置域名的时候提示“校验文件验证失败”
在微信小程序后台配置web-view的业务域名跟扫普通链接二维码打开小程序两项功能时, 一直提示"校验文件验证失败,请下载校验文件,上传到服务器指定的目录" 实际访问校验文件的路径 ...
- vue爬坑之路(axios 封装篇)
第一步还是先下载axios cnpm install axios -S第二步建立一个htttp.js import axios from 'axios'; import { Message } fro ...