Java 是值传递还是引用传递?

e377425051dae71474498894fc0b5d15.jpeg

3cd9b81a64acd0041a75fb35afa0289c.jpeg

作者 | 王磊

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

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

开篇先来曝答案,在 Java 语言中,本质只有值传递,而无引用传递,解释和证明详见正文。

说到值传递和引用传递我们不得不提到两个概念:值类型和引用类型。

1.值类型

通俗意义上来说,所谓的值类型指的就是 Java 中的 8 大基础数据类型:

  • 整数型:byte、int、short、long

  • 浮点型:float、double

  • 字符类型:char

  • 布尔类型:boolean

b1035772be2edbb235b48adb0cc573af.png

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

e1c96b527e1132b268ea4ace334869dc.png

2.引用类型

引用类型是指除值类型之外的数据类型,比如:

  • 接口

  • 数组

  • 字符串

  • 包装类(Integer、Double...)

1e0d69ed3a5070f57098e48842b4dd36.png


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

9352873c80be7d1944fdd7485032db09.png


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 的传参只会传递它的副本,并不会传递参数本身。

前面那个带引号的“引用传递”其实只是传递了它的引用副本,如下图所示:

f9f80649b41af9ad6ebb07a6fa3f448c.png


PS:《Java虚拟机规范》中对  Java 堆的描述是:“所有的对象实例以及数组都应当在堆上分配”。

所以我们在调用 new char[] 之后,可以看出 n 对象有了新地址,而原内容并未被修改,如果按照引用传递的思路来看的话,不管执行任何方式的修改都会改变原内容,因此我们可以更加确认 Java 语言中只有值传递,如下图所示:b9670e411448c64be8d89d10f18674b8.png

总结

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

a76dadf9baafd8dd81f8b91a5fd1297c.gif

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

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

相关文章

用于数据分析的Python – Pandas

大熊猫 (Pandas) Pandas is an open-source library built on top of NumPy Pandas是建立在NumPy之上的开源库 It allows for fast analysis and data cleaning and preparation 它允许快速分析以及数据清理和准备 It excels in performance and productivity 它在性能和生产力…

1022词法分析实验总结

经过这次词法分析的实验之后,收获良多。弥补了一些知识空洞,以前不懂的知识也弄懂了。 显然这都得力于组员之间的合作与帮助,一人负责编写,其他在旁边给想法同时学习。程序中运用了许多for,if,while等的循环…

SpringCloud基于RocketMQ实现分布式事务

前言分布式事务是在微服务开发中经常会遇到的一个问题,之前的文章中我们已经实现了利用Seata来实现强一致性事务,其实还有一种广为人知的方案就是利用消息队列来实现分布式事务,保证数据的最终一致性,也就是我们常说的柔性事务。消…

c# uri.host_C#| 具有示例的Uri.Host属性

c# uri.hostUri.Host属性 (Uri.Host Property) Uri.Host Property is the instance property of Uri class which used to get host components from URI. This property returns a string value. This property may generate System.InvalidOperationException exception. Uri…

VS使用和错误收集

USE: VS引用相对路径(需要说明的是,“..\”表示退出这一目录) VS 2005项目中添加lib库以及代码中的相对路径 ERROR: fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires M…

漫画:怎么证明sleep不释放锁,而wait释放锁?

wait 加锁示例public class WaitDemo {private static Object locker new Object();public static void main(String[] args) throws InterruptedException {WaitDemo waitDemo new WaitDemo();// 启动新线程,防止主线程被休眠new Thread(() -> {try {waitDemo…

机器学习 导论_机器学习导论

机器学习 导论什么是机器学习? (What is Machine Learning?) Machine learning can be vaguely defined as a computers ability to learn without being explicitly programmed, this, however, is an older definition of machine learning. A more modern defin…

就国内某个程序员问答网站的简单的分析

为什么80%的码农都做不了架构师?>>> 一、数据抓取 分析页面数据,设计数据表结构数据只要包含投票、回答数、问题状态、最后谁回答过、浏览数、问题标题、标签,数据样例如下:由于一开只打算爬问题标题,问题…

树的结构 数据结构_段树| 数据结构

树的结构 数据结构What is a segment tree? 什么是段树? A segment tree is a full binary tree where each node represents an interval. A node may store one or more data members of an interval which can be queried later. 段树是完整的二叉树&#xff0…

iOS开发中 常用枚举和常用的一些运算符(易错总结)

1、色值的随机值:#define kColorValue arc4random_uniform(256)/255.0 // arc4random_uniform(256)/255.0; 求出0.0~1.0之间的数字view.backgroundColor [UIColor colorWithRed:kColorValue green: kColorValue blue: kColorValue alpha: 0.5]; 2、定时器的使用&…

明明加了唯一索引,为什么还是产生重复数据?

前段时间我踩过一个坑:在mysql8的一张innodb引擎的表中,加了唯一索引,但最后发现数据竟然还是重复了。到底怎么回事呢?本文通过一次踩坑经历,聊聊唯一索引,一些有意思的知识点。1.还原问题现场前段时间&…

python字符串 切片_用于切片字符串的Python程序

python字符串 切片Given a string and number of characters (N), we have to slice and print the starting N characters from the given string using python program. 给定一个字符串和字符数( N ),我们必须使用python程序从给定的字符串中切片并打印开始的N个字…

nmap入门之主机发现

2019独角兽企业重金招聘Python工程师标准>>> #主机发现(HOST DISCOVERY) ##仅列出IP,不扫描 nmap -sL 192.168.70.0/24 > nmap_result.txt 2>&1##仅ping扫描,不扫描端口 nmap -sn 192.168.70.0/24##不ping扫…

面试官:为什么ConcurrentHashMap要放弃分段锁?

今天我们来讨论一下一个比较经典的面试题就是 ConcurrentHashMap 为什么放弃使用了分段锁,这个面试题阿粉相信很多人肯定觉得有点头疼,因为很少有人在开发中去研究这块的内容,今天阿粉就来给大家讲一下这个 ConcurrentHashMap 为什么在 JDK8 …

ruby .each_Ruby中带有示例的Array.each方法

ruby .eachRuby Array.each方法 (Ruby Array.each method) Array.each method can be easily termed as a method which helps you to iterate over the Array. This method first processes the first element then goes on the second and the process keeps on going on unt…

面试突击72:输入URL之后会执行什么流程?

作者 | 磊哥来源 | Java面试真题解析(ID:aimianshi666)转载请联系授权(微信ID:GG_Stone)在浏览器中输入 URL 之后,它会执行以下几个流程:执行 DNS 域名解析;封装 HTTP 请…

二层交换网络_网络中的第2层交换

二层交换网络二层交换简介 (Introduction to Layer 2 Switching) As you know hubs are not intelligent devices. Whenever a hub receives a frame, it broadcasts the frame in all ports. Also, the hub represents a single collision domain i.e. when any 2 hosts send …

最小化托盘示例工程

http://files.cnblogs.com/files/kekec2/BuyTicket.rar.gif转载于:https://www.cnblogs.com/kekec2/p/4914572.html

面试必备:TCP 经典 15 连问!

TCP协议是大厂面试必问的知识点。整理了15道非常经典的TCP面试题,希望大家都找到理想的offer呀1. 讲下TCP三次握手流程开始客户端和服务器都处于CLOSED状态,然后服务端开始监听某个端口,进入LISTEN状态第一次握手(SYN1, seqx),发…

range函数python_range()函数以及Python中的示例

range函数pythonPython range()函数 (Python range() function) The range() is a built-in function in Python which returns the sequence of values. It is used where we need to perform a specific action for a limited number of times. In general, if we write rang…