多图证明,Java到底是值传递还是引用传递?

开篇先来曝答案,在 Java 语言中,本质只有值传递,而无引用传递,解释和证明详见正文。
说到值传递和引用传递我们不得不提到两个概念:值类型和引用类型。
1.值类型
通俗意义上来说,所谓的值类型指的就是 Java 中的 8 大基础数据类型:
- 整数型:byte、int、short、long
- 浮点型:float、double
- 字符类型:char
- 布尔类型:boolean

从 JVM 层面来讲:所谓的值类型指的是在赋值时,直接在栈中(Java 虚拟机栈)生成值的类型,如下图所示:

2.引用类型
引用类型是指除值类型之外的数据类型,比如:
- 类
- 接口
- 数组
- 字符串
- 包装类(Integer、Double...)

从 JVM 的层面来讲,所谓的引用类型是指,在初始化时将引用生成栈上,而值生成在堆上的这些数据类型,如下图所示:

PS:关于包装类为什么是引用类型?我们后面的文章会单独讲,记得关注:Java中文社群
3.值传递
值传递(Pass By Value)指的是方法传参时,传递的是原内容的副本,因此对副本进行如何修改都不会影响原内容。
实现代码如下:
public class PassTest {
public static void main(String[] args) {
int age = 18;
System.out.println("调用方法前:" + age);
intTest(age);
System.out.println("调用方法后:" + age);
}
private static void intTest(int age) {
age = 30;
System.out.println("方法中修改为:" + age);
}
}
程序的执行结果为:
调用方法前:18
方法中修改为:30
调用方法后:18
从上述结果可以看出,在方法中修改参数并未影响原内容,我们把这种传参方式称之为值传递。
4.引用传递
引用传递(Pass By Reference)指的是方法传参时,传递的是参数本身,因此对参数进行任意修改都会影响原内容。
模拟“引用传递”的实现代码如下:
public class PassTest {
public static void main(String[] args) {
char[] name = {'磊', '哥'};
System.out.println("调用方法前:" + new String(name));
paramTest(name);
System.out.println("调用方法后:" + new String(name));
}
private static void paramTest(char[] n) {
n[1] = '神';
System.out.println("方法中修改为:" + new String(n));
}
}
程序的执行结果为:
调用方法前:磊哥
方法中修改为:磊神
调用方法后:磊神
从上述的结果可以看出在 paramTest 方法中修改了参数之后,在 main 方法中再打印参数时,发现参数的值也跟着发生了改变,那么似乎我们可以得出结论,Java 中貌似也有“引用传递”,然而事实并非如此,我们接着看。
5.真假“引用传递”
我们给上面的代码添加一行,如下所示:
public class PassByValue {
public static void main(String[] args) {
char[] name = {'磊', '哥'};
System.out.println("调用方法前:" + new String(name));
paramTest(name);
System.out.println("调用方法后:" + new String(name));
}
private static void paramTest(char[] n) {
n = new char[2]; // 添加此行代码
n[1] = '神';
System.out.println("方法中修改为:" + new String(n));
}
}
程序的执行结果为:
调用方法前:磊哥
方法中修改为:神
调用方法后:磊哥
从上述结果可以看出,当我们在 paramTest 方法中添加 new char[] 之后,“引用传递”就突然变值传递了?为什么?
这是因为,在 Java 语言中本质上只有值传递,也就说 Java 的传参只会传递它的副本,并不会传递参数本身。
前面那个带引号的“引用传递”其实只是传递了它的引用副本,如下图所示:

PS:《Java虚拟机规范》中对 Java 堆的描述是:“所有的对象实例以及数组都应当在堆上分配”。
所以我们在调用 new char[] 之后,可以看出 n 对象有了新地址,而原内容并未被修改,如果按照引用传递的思路来看的话,不管执行任何方式的修改都会改变原内容,因此我们可以更加确认 Java 语言中只有值传递,如下图所示:

总结
通过本文的内容,我们可以得出:在 Java 语言中只有值传递,方法传参时只会传递副本信息而非原内容。我们还知道了基础数据类型会直接生成到栈上,而对象或数组则会在栈和堆上都生成信息,并将栈上生成的引用,直接指向堆中生成的数据,如下图所示:
@一个正经的程序员

长按二维码关注
赶紧来给Louis一个“关注”,“点赞”,“在看”吧,这才是对我最大的鼓励哦~
多图证明,Java到底是值传递还是引用传递?的更多相关文章
- 188W+程序员关注过的问题:Java到底是值传递还是引用传递?
在逛 Stack Overflow 的时候,发现了一些访问量像阿尔卑斯山一样高的问题,比如说这个:Java 到底是值传递还是引用传递?访问量足足有 188万+,这不得了啊!说明有很多很多的程序员被这个 ...
- [转帖]Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递?
Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递? http://www.itpub.net/2019/12/03/4567/ 在逛 Stack Overfl ...
- Java 到底是值传递还是引用传递
作者:Intopass链接:https://www.zhihu.com/question/31203609/answer/50992895来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业 ...
- Java中到底是值传递还是引用传递?
Java中到底是值传递还是引用传递? 我们先回顾一下基本概念 实参和形参 参数在编程语言中是执行程序需要的数据,这个数据一般保存在变量中.在Java中定义一个方法时,可以定义一些参数, 举个例子: p ...
- Java 到底是值传递还是引用传递?
关于这个问题,引发过很多广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同,甚至很多人理解的是错误的.还有的人可能知道Java中的参数传递是值传递,但是说不出来为什么. 在开始深入讲解之前,有必要 ...
- java参数传递时到底是值传递还是引用传递
java参数传递时到底是值传递还是引用传递(baidu搜集) 问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解. 原题是:当一 ...
- Java调用函数传递参数到底是值传递还是引用传递
今天翻看微信上有关Java技术的公众号时,看到了一篇关于Java中值传递的问题,文章讨论了在Java中调用函数进行传参的时候到底是值传递还是引用传递这个面试时会问到的问题.之前也接触过类似的问题,但只 ...
- JAVA方法中参数到底是值传递还是引用传递
当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递? 答:是值传递.Java 语言的参数传递只有值传递.当一个实例对象作为参数被传递到方法中时,参 ...
- 面试官:兄弟,说说Java到底是值传递还是引用传递
二哥,好久没更新面试官系列的文章了啊,真的是把我等着急了,所以特意过来催催.我最近一段时间在找工作,能从二哥的文章中学到一点就多一点信心啊! 说句实在话,离读者 trust you 发给我这段信息已经 ...
随机推荐
- 在线快速创建SpringBoot项目
都2020年了,你还在手动创建SpringBoot项目吗?今天教你在线快速创建一个SpringBoot项目,瞬间高大上有木有! 进入正题,首先打开创建SpringBoot的官网:https://sta ...
- 没有Qt Quick UI,没有 Qt Quick Project
书上写的是File ‣ New File or Project ‣ Qt Quick Project ‣ Qt Quick UI 但实际上是File ‣ New File or Project ‣ O ...
- doT模板双重循环模板渲染方法
doT模板作为一个前端渲染模板,有着非常显著的有点.1.轻量.2.快捷.3.无依赖. 本文介绍一种几乎所有模板都会遇到的问题,双重循环渲染.我们知道在dot模板中循环渲染用的是{{~ it:value ...
- python 基础-文件读写'r' 和 'rb'区别
原文链接: python基础-文件读写'r' 和 'rb'区别 一.Python文件读写的几种模式: r,rb,w,wb 那么在读写文件时,有无b标识的的主要区别在哪里呢? 1.文件使用方式标识 'r ...
- 第3关-input()函数
第3关-input()函数 一.input()函数 import time print('亲爱的同学:') time.sleep(1) print('我们愉快地通知您,您已获准在霍格沃茨魔法学校就读. ...
- [Window编程][VC6.0++][error LNK2001: unresolved external symbol __imp__PlaySoundA@12]
错误情况 这几天看<Windows游戏编程大师技巧>,在看第三章的时候,把书上的例子敲了一边,但是出现了下述错误,最后在网上找到了解决方法. 错误截图 解决方法 在main.cpp头文件下 ...
- python连接mysql中报错1064修改方法
Python是编程语言,MySQL是数据库,它们是两种不同的技术:要想使Python操作MySQL数据库需要使用驱动.这里选用PyMySQL驱动.下载地址: https://pypi.python.o ...
- Android 引入第三方类库
- 国内几大seo高手(夫唯,王通,久久)的技术分析
http://www.wocaoseo.com/thread-146-1-1.html 目前学习seo的人越来越多了,这种技术的普及和推广也在不断的扩大,先进的好的培训机构不断涌现,很多高水平老师都在 ...
- rust 模块组织结构
rust有自己的规则和约定用来组织模块,比如一个包最多可以有一个库crate,任意多个二进制crate.导入文件夹内的模块的两种约定方式... 知道这些约定,就可以快速了解rust的模块系统. 先把一 ...