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

作者 | 王磊

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

开篇先来曝答案,在 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 语言中只有值传递,方法传参时只会传递副本信息而非原内容。我们还知道了基础数据类型会直接生成到栈上,而对象或数组则会在栈和堆上都生成信息,并将栈上生成的引用,直接指向堆中生成的数据,如下图所示:

往期推荐

阿里为什么推荐使用LongAdder,而不是volatile?

Java 中 10 大坑爹功能!

面试系列第2篇:回文字符串判断的3种方法!

List 集合去重的 3 种方法

阿里的简历多久可以投递一次?次数多了有没有影响?可以同时进行吗?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/545895.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vb中filecopy拷贝文件

FileCopy("源文件名","目标文件名")两个参数都是必选的,且都包含路径。在VB中filecopy函数可以直接调用。而CopyFile函数则不能要先定义filesystemobject变量,然后才能用。有过copyFile比fileCopy的功能有所不同。FileCopy是单个文件的copy,目标…

scala提取字符串中数字_如何在Scala中以字符串或数字的形式获取日期,月份和年份?...

scala提取字符串中数字The "calendar" class handles working with date and time in Scala, the class generates the current time in the following format, “ calendar”类处理Scala中的日期和时间 ,该类以以下格式生成当前时间, Thu Ap…

图解面试题:找出数组中重复的数字?

今天分享的题目来源于 LeetCode 上的剑指 Offer 系列 面试题03. 数组中重复的数字。题目链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/一、题目描述 找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0&#xf…

vb中picturebox透明时看到下面的picturebox中图片

在加载窗体时,把PictureBox1的背景指定为透明,再把PictureBox1指定为PictureBox2的父容器就可以实现PictureBox2透明于PictureBox1且都透明与窗体背景了。VB2010环境下的。代码如下: Private Sub Form1_Load(ByVal sender As System.Object, …

Java ObjectStreamClass getSerialVersionUID()方法(带示例)

ObjectStreamClass类getSerialVersionUID()方法 (ObjectStreamClass Class getSerialVersionUID() method) getSerialVersionUID() method is available in java.io package. getSerialVersionUID()方法在java.io包中可用。 getSerialVersionUID() method is used to get the s…

知方可补不足~数据库名称和数据库别名不同了怎么办

回到目录 当你的数据库安装成功后,你修改了计算机名称,这时,你的sqlserver名称与别名可能就不相同了,当这两个名称不相同时,你再使用sql的发布与订阅功能时,将会被提示出错,“请使用服务名称&am…

调研了100+开源博客,发现这5个最好用!

最近想倒腾一下博客,看了很多现成的比较成熟的开源博客系统,自己也简单从下面几个维度总结对比了一下:star 数量技术选型社区生态当然啦!好东西不能独享,下面简单分享一下我所做的笔记(文末有提供所有项目的…

批处理编程详解

批处理编程详解小引:最近好多猜测弱口令的病毒在网上流行,比如前段时间闹得很厉害的Worm.Dvldr 蠕虫就是一个典型。这些病毒有个共同点就是利用批处理来进行ipc$连接,从而来猜测管理员的口令达到控制服务器的目的。病毒由几个文件和几个复杂的…

Java Object Class boolean equals(Object o)方法与示例

对象类布尔值等于(对象o) (Object Class boolean equals(Object o)) This method is available in package java.lang.Object.equals(Object o). 软件包java.lang.Object.equals(Object o)中提供了此方法。 This method is used to check the object with the specified object…

3种时间格式化的方法,SpringBoot篇!

时间格式化在项目中使用频率是非常高的,当我们的 API 接口返回结果,需要对其中某一个 date 字段属性进行特殊的格式化处理,通常会用到 SimpleDateFormat 工具处理。SimpleDateFormat dateFormat new SimpleDateFormat("yyyy-MM-dd"…

linux系统怎么改为中文版(转)

linux系统安装好后怎么改为中文版呢?今天就跟大家介绍下linux系统改为中文版的方法,希望能帮助到大家! 以下是linux系统改为中文版的四种方法,一起来看看: 方法1:写入环境变量 echo "export LANG"…

写一个头文件

#ifndef _(文件名)_H #define _(文件名)_H #include<标准库头文件> ……&#xff08;所有函数声明&#xff09; #endif 头文件是对函数的声明&#xff0c;在对其引用时用“……”和<……>两种&#xff0c;如果这个头文件是自己写的就用“”&#xff0c;例如#i…

Command10,Access数据库

我的按钮名为Command10&#xff0c;Access文档新建在当前目录下&#xff0c;代码如下Private Sub Command10_Click()Dim cat As ADOX.CatalogSet cat New ADOX.Catalog在当前目录下建立名为newdata的Access数据库cat.Create ("ProviderMicrosoft.Jet.OLEDB.4.0;Data Sour…

b树范围查找_使用段树查找最大查询范围

b树范围查找The following question/problem is asked on http://www.spoj.com/problems/GSS1/ 在http://www.spoj.com/problems/GSS1/上询问以下问题/问题 Problem: 问题&#xff1a; A sequence is given: A[1], A[2], ..., A[N] .( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). …

两难!先更新数据库再删缓存?还是先删缓存再更新数据库?

前言当我们在做数据库与缓存数据同步时&#xff0c;究竟更新缓存&#xff0c;还是删除缓存&#xff0c;究竟是先操作数据库&#xff0c;还是先操作缓存&#xff1f;本文带大家深度分析数据库与缓存的双写问题&#xff0c;并且给出了所有方案的实现代码方便大家参考。本篇文章主…

c++ list sort

1. bool operator < (S & b) {return ID < b.ID;} struct S {std::string firstname;std::string secondname;int ID;bool operator < (S & b) {return ID < b.ID;}// 重新定义小于&#xff0c;因为默认的sort函数调用的操作符是<&#xff0c;所以我…

负数在计算机中如何表示?

取一个负数如-5&#xff0c;其原码就是其绝对值5的原码&#xff0c;但最高位为1&#xff0c;&#xff08;负数最高位为1&#xff0c;正数最高位为0&#xff09;&#xff0c;其反码就是对原码取反&#xff08;最高位不参与取反&#xff09;&#xff0c;补码就是对反码1&#xff…

String中删除空格的7种方法!

字符串&#xff0c;是Java中最常用的一个数据类型了。我们在日常开发时候会经常使用字符串做很多的操作。比如字符串的拼接、截断、替换等。本文我们介绍一个比较常见又容易被忽略的一个操作&#xff0c;那就是移除字符串中的空格。其实&#xff0c;在Java中从字符串中删除空格…

pictureBox1.Image的获得图片路径的三种方法

1.绝对路径: this.pictureBox2.ImageImage.FromFile("D://1.jpg"); 2.相对路径: Application.StartupPath; 可以得到程序根目录 this.pictureBox2.ImageImage.FromFile(Application.StartupPath "//1.gif"); 3.获得网络图片的路径 this.pictureBox2.Imag…

借助datetime和pyttsx3在Python中创建闹钟

Modules used: 使用的模块&#xff1a; To create this script, we will use 3 modules: 要创建此脚本&#xff0c;我们将使用3个模块&#xff1a; datetime 约会时间 time 时间 pyttsx3 pyttsx3 datetime module: datetime is an inbuilt python module which will help us …