news 2026/6/10 22:54:07

Java的值传递与“引用传递”

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java的值传递与“引用传递”

核心结论先行:Java 只有值传递,没有引用传递。

为了彻底搞懂这个问题,需要先明确两个定义,然后通过代码示例一步步验证。

1. 先澄清两个关键概念

值传递:方法调用时,实参将自己的值的副本传递给形参,在方法内部修改形参,不会影响实参本身。

引用传递:方法调用时,实参将自己的内存地址直接传递给形参,在方法内部修改形参指向的内容,直接影响实参指向的内容。

关键区别在于:值传递传递的是值的拷贝;引用传递传递的是内存地址本身。

2. Java 中的两种数据类型

注意下面的措辞 —— 是引用类型,不要看成引用传递。引用类型可以理解成一种基本属性或者标签,引用传递可以理解成一种行为

基本类型:变量直接存储本身(如 int a = 10; a 里面就是 10)。

引用类型:变量存储的是对象的引用(可以理解为内存地址),真正的对象在堆内存中(如 Person p = new Person(); p 里面存储的是指向 Person 对象的地址)。

3. 通过代码验证“只有值传递”

3.1. 场景一:传递基本类型

基本类型有:byte、short、int、long、float、double、char、boolean

public class Test { public static void main(String[] args) { int num = 10; System.out.println("调用前:num = " + num); // 输出 10 changeValue(num); System.out.println("调用后:num = " + num); // ? } public static void changeValue(int a) { a = 20; // 修改的是形参 a 的副本 System.out.println("方法内部:a = " + a); // 输出 20 } }

这里问号输出的结果是 :10

解释

  • int 是基本类型,所以 main 方法中的 num 变量存储的是10这个数值本身。
  • 调用changeValue(num)时,JVM 将10这个值拷贝一份,传给形参a。(值传递)
  • 现在内存中有两个独立的空间:main 的 num 和 changeValue 的 a,都存着10
  • 在方法内修改a = 20,只是修改 a 的那个副本,main 的 num 丝毫未受影响。

结论:基本类型肯定是值传递。

3.2. 场景二:传递引用类型

引用类型有:数组、对象

这里直接看案例,可以思考问号会是什么值?

class Person { String name; Person(String name) { this.name = name; } } public class Test { public static void main(String[] args) { Person p1 = new Person("张三"); System.out.println("调用前:p1.name = " + p1.name); // 张三 changeName(p1); System.out.println("调用后:p1.name = " + p1.name); // ? } public static void changeName(Person p) { p.name = "李四"; // 通过引用修改了对象的属性 System.out.println("方法内部:p.name = " + p.name); // 李四 } }

答案是:李四。

这是最容易误解的地方,看到方法内修改了对象的属性,外面也变了,就认为这是引用传递。

别急,再看下面这个例子,想想这里的问号是什么值?

public class Test { public static void main(String[] args) { Person p1 = new Person("张三"); System.out.println("调用前:p1.name = " + p1.name); // 张三 changeReference(p1); System.out.println("调用后:p1.name = " + p1.name); // ? } public static void changeReference(Person p) { p = new Person("王五"); // 让 p 指向一个新对象 System.out.println("方法内部:p.name = " + p.name); // 王五 } }

答案是:张三。看下面的运行截图:

所以如果 Java 支持“引用传递”,那么这个案例中 main 中的 p1 应该也指向新对象“王五”。但结果它还是“张三”。

形象解释:

  1. main 方法中Person p1 = new Person("张三")p1是一个变量,想象它存储的是一个“地址”(引用),地址指向堆内存中Person(“张三”)这个对象。假设是p1变量的内容 0x123。
  2. 调用changeReference(p1):将p1中存储的地址0x123这个值,拷贝一份,赋值给形参p。现在p也存着 0x123,也指向同一个对象。传递的是 0x123 这个数值,而不是 p1 变量本身。这就是值传递!
  3. 所以这就是为什么第一个例子中修改p.name成功了。拟人表达就是:因为pp1都拿着同一个地址0x123。p 顺着地址去找到这个对象,并且把对象的名字给改了,改完之后当 p1 也顺着这个地址找到这个对象时,发现名字就变了。
  4. 第二个案例中,在方法内执行p = new Person(“王五”)。拟人表达就是:p 把手上的地址坐标给改掉了,然后拿着新地址去找那个地址对应的对象,假设从0x123改为0x456(新对象)
  5. 但 main 中的p1仍然拿着0x123,纹丝不动。所以第二个案例最后输出的还是“张三”。

结论:引用类型也是值传递。

4. 图示理解

4.1. 修改对象属性p.name = "李四"

初始状态:mainp1 = new Person("张三")

调用changeName(p1):传递地址值的拷贝

方法内执行p.name = "李四":通过任意引用修改对象

结果p1.name变成"李四",因为两个变量指向同一个对象。

4.2. 改变引用指向p = new Person("王五")

初始状态(同上)

方法内执行p = new Person("王五"):改变形参的引用

结果p1仍然指向对象A(name = "张三"),形参p指向了新对象B。

5. 最终结论

  1. Java 只有值传递,没有引用传递。
  2. 当参数是基本类型时,传递的是数值字面量的拷贝。
  3. 当参数是引用类型时,传递的是引用的值(地址编号)的拷贝。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 22:52:23

科技是市场的唯一

昨天美股科技股大幅反弹,今天早上日本和韩国股市开盘也是大涨,韩国股市更是涨到熔断。韩国股市昨天大跌8个多点,今天大涨8个多点,这波动真的太剧烈了。外围科技股都在反弹大涨,A股自然跟着涨,开盘就是高开。…

作者头像 李华
网站建设 2026/6/10 22:45:58

在wps复制表格后直接存储图片到指定位置的工具

一个在wps复制表格后直接存储图片到指定位置的工具,无需中转微信复制为图片再另存为 https://download.csdn.net/download/z1696853278/92959326 功能特点 - Excel 复制的excel区域后,直接存储剪贴板的 PNG 图片到文件夹 - 支持自定义输出路径和自定义…

作者头像 李华
网站建设 2026/6/10 22:45:04

Codex Windows App 运行发热问题-完整排查报告

基础信息排查日期:2026-06-08 ~ 06-09 环境:Windows 11 家庭中文版 Intel Core Ultra X7 358H Codex 桌面版 26.602.71036一、摘要(一句话版) 你以为"Codex 只是云端推理的壳子、本地不该发热",但实测发现…

作者头像 李华
网站建设 2026/6/10 22:42:02

发SCI心态崩了?来试试1区天菜PINN机器学习!简单好学易上手!

聊聊AI4S的顶流赛道:PINN机器学习。这是个低投入、高产出、高命中率的发文方向,尤其适合缺乏大数据/算力,但擅长物理建模,想要快速冲顶会顶刊的朋友。这方向创新点也很好找,比如方法层创新,PINNX任意组合就…

作者头像 李华