java值传递与引用传递

news/2024/11/24 2:18:10/

没有繁琐的各种内存指向图片,而是从概念中进行解释

值传递场景

值传递包含String类型以及基本数据类型,仅仅传递值,
基本上只会有一种场景

   @Testpublic void testModify(){String str1 = "1";String str2 = this.modifyStr(str1);System.out.println("str1===>"+str1);  // str1===>1System.out.println("str2===>"+str2);  // str2===>2}private String modifyStr(String str){	// 形参strstr = "2";		// 不管在这里进行什么操作,什么交换之类的,都不会改变实参(str1)return str;	}

此时吧值赋给str2了,str1的值没有变化,吧String类型换成其他的int类型等基本数据类型,都是有效的

引用传递场景

引用传递基本上会包含4种场景,其中最后2种主要探讨的是返回值,网络资料中较少提到
假设一个User类,仅有一个属性id,注入Getter,Setter方法

// 使用lombok自动写入getter,setter方法
@Data
public class User{private String id;
}

场景1

 	@Testpublic void testModify(){User user1 = new User();user1.setId("1");System.out.println("user1-->HashCode:"+user1.hashCode());	// user1-->HashCode:111this.modifyUser1(user1); 	System.out.println("user1.getId()===>"+user1.getId()); // user1.getId()===>2}private User modifyUser1(User user){  // 形参useruser.setId("2");	// 引用了实参user1的地址,修改了实参user1的属性,所以user1也改了System.out.println("user-->HashCode:"+user.hashCode());	// user1-->HashCode:111return user;}

此时 modifyUser1() 方法里接收到的是user1的引用,因此改变形参user的值就等于改变user1的值。modifyUser1() 方法内user的hashCode和user1的hashCode一样,因此地址一样

场景2

    @Testpublic void testModify(){User user1 = new User();user1.setId("1");System.out.println("user1-->HashCode:"+user1.hashCode());	// user1-->HashCode:111this.modifyUser2(user1); 	System.out.println("user1.getId()===>"+user1.getId()); // user1.getId()===>1}private User modifyUser2(User user){ // 形参useruser = new User();  // 如果没有这行new User,则和场景1一样引用实参user1的地址// 但是new User()了,地址指向发生了改变,因此此时user为一个新的对象user.setId("2");	System.out.println("user-->HashCode:"+user.hashCode());	// user1-->HashCode:222return user;}

此时 modifyUser2() 方法里一开始接收到的是user1的引用,但是后面new User()了,创建了个新的对象,引用改变了(user1的hashCode不等于user的hashCode了),指向的是new User,之后形参user的修改基于的都是对new User()的修改了

场景3
当引入返回值时,重新看看modifyUser1的方法

    @Testpublic void testModify(){User user1 = new User();user1.setId("1");System.out.println("user1-->HashCode:"+user1.hashCode());	// user1-->HashCode:111User user2 = this.modifyUser1(user1); 	System.out.println("user1.getId()===>"+user1.getId()); // user1.getId()===>2user2.setId("3");System.out.println("user2.getId()===>"+user2.getId()); // user2.getId()===>3System.out.println("user1.getId()===>"+user1.getId()); // user1.getId()===>3}private User modifyUser1(User user){  // 形参useruser.setId("2");	// 引用了实参user1的地址,修改了实参user1的属性,所以user1也改了System.out.println("user-->HashCode:"+user.hashCode());	// user1-->HashCode:111return user;}

最后会发现user1和user2的id都为3,当把返回值赋给user2时,实际上返回的是引用,相当于user2 与user1的地址是一样的,所以此时修改user2的值,user1的值也会发生改变,实际上等价于以下代码

@Testpublic void testModify(){User user1 = new User();user1.setId("1");User user2 = user1;			// 将user1的引用赋给user2,// 此时修改user1等于改user2,修改user2等于改user1user2.setId("3");System.out.println(user1.getId());		// 3System.out.println(user2.getId());		// 3}

场景4
当引入返回值时,重新看看modifyUser2的方法

	@Testpublic void testModify(){User user1 = new User();user1.setId("1");System.out.println("user1-->HashCode:"+user1.hashCode());	// user1-->HashCode:111User user2 = this.modifyUser2(user1);System.out.println("user2-->HashCode:"+user2.hashCode());  // user2-->HashCode:222System.out.println("user1.getId():"+user1.getId());		// user1.getId():1System.out.println("user2.getId():"+user1.getId());		// user2.getId():2}private User modifyUser2(User user){  // 形参useruser = new User();  // 如果没有这行new User,则和场景1一样引用实参user1的地址// 但是new User()了,地址指向发生了改变,因此此时user为一个新的对象user.setId("2");System.out.println("user-->HashCode:"+user.hashCode()); // user-->HashCode:222return user;		// 将引用返回}

最后会发现user1的id仍然是1,user2的id则为2,这是因为在modifyUser2方法里new User()了,而这个new出来的user对象最后引用赋给了user2(两者hashCode都是一样的,都为222),而user1的hashCode仍为111,此时user1和user2地址不一样,任意修改user1也不会影响user2,实际上等价于以下代码

@Testpublic void testModify(){User user1 = new User();user1.setId("1");User user2 = new User();		// 等价于在modifyUser2方法里new出来的对象user2.setId("2");// 此时user1和user2的引用就完全不一样了,修改互不影响System.out.println(user1.getId());		// 1System.out.println(user2.getId());		// 2}

http://www.ppmy.cn/news/1296433.html

相关文章

Qt中图片旋转缩放操作

在我们开发过程中,难免会遇到加载图片的问题,在上一个开发项目里我就遇到了图片缩放的问题,所以,我决定将这一部分好好研究,记录下来,希望对大家有帮助哟~ 在讲解之前,我们先看一看具体的展示效…

LabVIEW在高精度机器人视觉定位系统中的应用

在现代工业自动化中,精确的机器人视觉定位系统对于提高生产效率和产品质量至关重要。LabVIEW软件,以其卓越的图像处理和自动化控制功能,在这一领域发挥着重要作用。本案例将展示LabVIEW如何帮助开发和实现一个高精度的机器人视觉定位系统&…

MySQL 存储引擎和索引类型介绍

1. 引言 MySQL 是一个流行的关系型数据库管理系统,提供多种存储引擎以满足不同的业务需求。本文将介绍几种常见的 MySQL 存储引擎和索引类型比较,并给出相应的示例。 2. 存储引擎概述 2.1 InnoDB 存储引擎 InnoDB 是 MySQL 的默认存储引擎&#xff0…

React-hook-form-mui(一):基本使用

前言 在项目开发中,我们选择了ReactMUI作为技术栈。在使用MUI构建form表单时,我们发现并没有与antd类似的表单验证功能,于是我们选择了MUI推荐使用的react-hook-form-mui库去进行验证。但是发现网上关于这个库的使用方法和demo比较少且比较简…

安卓上使用免费的地图OpenStreetMap

前一段使用了微信的地图,非常的好用。但是存在的问题是海外无法使用,出国就不能用了; 其实国内三家:百度,高德,微信都是一样的问题,当涉及到商业使用的时候需要付费; 国外除了谷歌…

Unity中Shader的_Time精度问题

文章目录 前言一、U方向上优化二、V方向上优化在这里插入图片描述 三、最终代码1、效果2、Shader 前言 在Unity的Shader中,使用了_Time来达到UV的流动效果,普遍会出现一个问题。我们的UV值会随着时间一直增加(uv值增加了,但是因为…

设计模式篇章(1)——理论基础

设计模式:在软件开发中会面临许多不断重复发生的问题,这些问题可能是代码冗余、反复修改旧代码、重写以前的代码、在旧代码上不断堆新的代码(俗称屎山)等难以扩展、不好维护的问题。因此1990年有四位大佬(GoF组合&…

【系统高级-环境变量】path配置一整行,而不是列表

这是列表编辑方便。但是不知道为什么变成一行,非常的令人抓狂,经过研究发现,第一个环境变量必须为C:\Windows\system32 开头才可以 文章如下 修改环境变量中的一行变成列表形式_环境变量编辑不是列表-CSDN博客