188W+程序员关注过的问题:Java到底是值传递还是引用传递?
在逛 Stack Overflow 的时候,发现了一些访问量像阿尔卑斯山一样高的问题,比如说这个:Java 到底是值传递还是引用传递?访问量足足有 188万+,这不得了啊!说明有很多很多的程序员被这个问题困扰过。实话实说吧,我就是其中之一。
来回顾一下提问者的问题:
我一直认为 Java 是按引用传递的,但是我看一些博客上说不是的。我就纳闷了,Java 到底是值传递还是引用传递?值传递和引用传递有什么区别呢?
如果你也曾被这个问题困扰过,或者正在被困扰,就请随我一起来梳理一下问题的答案。打怪进阶喽!
01、值传递和引用传递
什么是值传递,什么是引用传递?我们需要先把这两个定义搞清楚,才能搞清楚 Java 是按值传递还是按引用传递。
值传递(pass by value)是指在调用方法时将实参复制一份传递到方法中,这样当方法对形参进行修改时不会影响到实参。
引用传递(pass by reference)是指在调用方法时将实参的地址直接传递到方法中,那么在方法中对形参所进行的修改,将影响到实参。
上面是比较官方的定义,读起来不免生硬。在我看来,值传递和引用传递的关键区别有两点:
1)调用方法时有没有对实参进行复制。
2)方法内对形参的修改会不会影响到实参。
what?值传递和引用传递还没有搞清楚,又来两个新名词:实参和形参。别急,别急。
02、实参和形参
实参和形参理解起来比值传递和引用传递容易的多,前者就好像是一元一次方程,后者就像是一元二次方程。
形参:定义方法名和方法体的时候使用的参数,目的是用来接收调用该方法时传入的参数。
实参:在调用有参方法时传入的参数,方法名后面的括号中的参数通常被称为“实参”。
大家应该都写过“hello world”程序了,就像下面这样。
public class Cmower {
public static void main(String[] args) {
System.out.println("hello world");
}
}
其中 args 就相当于是形参,而字符串“hello world”就相当于是实参。如果觉得这个例子不容易理解,那再来看一个。
public class Cmower {
public static void main(String[] args) {
Cmower cmower = new Cmower();
cmower.sop("沉默王二");
}
public void sop(String name) {
System.out.println("hello " + name);
}
}
其中“沉默王二”为实参;有参方法 sop(String name) 中的 name 为形参。形参就好像实参与被调用方法之间的一个桥梁,否则调用者没法传递参数,被调用的方法无法接收参数。
03、基本类型是值传递的
Java 中的数据类型可以分为两种,一种是基本类型,一种是引用类型。我相信大家在看本篇文章之前,就能够达成这样一个共识:基本类型是值传递的。这一点毫无疑问。
public class Cmower {
public static void main(String[] args) {
Cmower cmower = new Cmower();
int age = 18;
cmower.sop(age);
System.out.println("main 中的 age " + age);
}
public void sop(int age) {
age = 28;
System.out.println("sop 中的 age " + age);
}
}
上面这段代码中,sop() 方法的实参 age 为 18,尽管 sop() 方法的形参被修改为 28,但并不会影响实参的值。这一点可以从输出结果中加以证明。
sop 中的 age 28
main 中的 age 18
具体的执行过程如下图所示。

04、引用类型是值传递吗?
大家之所以不确定 Java 是值传递的还是引用传递的,原因就出在这个引用类型上面。单从字面的意思上就容易搞混:引用类型不是引用传递难道还是值传递?
public class Cmower {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
Cmower cmower = new Cmower();
cmower.setName("沉默王二");
cmower.sop(cmower);
System.out.println("main 中的 cmower " + cmower.getName());
}
public void sop(Cmower cmower) {
cmower.setName("沉默王三");
System.out.println("sop 中的 cmower " + cmower.getName());
}
}
在 main() 方法中,我们通过 new 关键字创建了一个对象 cmower,并将其 name 属性设置为“沉默王二”;然后将实参 cmower 传递给 sop() 方法,在 sop() 方法中将形参 cmower 的 name 属性修改为“沉默王三”。输出结果是什么样子呢?
sop 中的 cmower 沉默王三
main 中的 cmower 沉默王三
呀!实参 cmower 的属性 name 竟然不是“沉默王二”而是“沉默王三”了!看看,看看,Java 不是值传递吧?
别急别急。我们在 main 方法中追加几行代码。
Cmower cmower = new Cmower();
cmower.setName("沉默王二");
Cmower old = cmower;
cmower.sop(cmower);
System.out.println("main 中的 cmower " + cmower.getName());
System.out.println(old == cmower);
old == cmower 会是 true 还是 false 呢?闭上眼睛想一想。如果实在是想不出,抛一枚硬币吧,反正不是 true 就是 false。假如引用类型是引用传递的,根据引用传递的定义(形参的修改将会影响到实参),那么结果一定就是 false。
我们来看一下输出结果:
sop 中的 cmower 沉默王三
main 中的 cmower 沉默王三
true
true?开什么玩笑?
不好意思,没有开玩笑。Java 的确是值传递的。只不过,引用类型在调用有参方法的时候,传递的是对象的引用,并不是对象本身。而对象的引用在传递的过程中并没有发生改变,虽然对象本身发生了变化。可以通过下面这幅图感受一下。

这下理解了吧?
05、总结
来看下面这段代码。
int age = 18;
String name = "沉默王二";
age 是基本类型,所以值就直接保存在变量中;而 name 是引用类型,变量中保存的只是对象的内存地址,这种变量一般称之为对象的引用。
基本类型作为参数被传递时肯定是值传递;引用类型作为参数被传递时也是值传递,只不过“值”为对应的引用。
好了各位读者朋友们,以上就是本文的全部内容了。能看到这里的都是最优秀的程序员,我必须要为大家点个赞
188W+程序员关注过的问题:Java到底是值传递还是引用传递?的更多相关文章
- 多图证明,Java到底是值传递还是引用传递?
开篇先来曝答案,在 Java 语言中,本质只有值传递,而无引用传递,解释和证明详见正文. 说到值传递和引用传递我们不得不提到两个概念:值类型和引用类型. 1.值类型 通俗意义上来说,所谓的值类型指的就 ...
- Java 到底是值传递还是引用传递?
关于这个问题,引发过很多广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同,甚至很多人理解的是错误的.还有的人可能知道Java中的参数传递是值传递,但是说不出来为什么. 在开始深入讲解之前,有必要 ...
- Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结
这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...
- java中参数传递--值传递,引用传递
java中的参数传递——值传递.引用传递 参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用. ...
- java 传参方式--值传递还是引用传递
java 传参方式--值传递还是引用传递 参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递.写它是为了揭穿普遍存在的一种神话,即认为 Java 应用程序按引用 ...
- [转帖]Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递?
Stack Overflow上188万浏览量的提问:Java 到底是值传递还是引用传递? http://www.itpub.net/2019/12/03/4567/ 在逛 Stack Overfl ...
- 面试官:兄弟,说说Java到底是值传递还是引用传递
二哥,好久没更新面试官系列的文章了啊,真的是把我等着急了,所以特意过来催催.我最近一段时间在找工作,能从二哥的文章中学到一点就多一点信心啊! 说句实在话,离读者 trust you 发给我这段信息已经 ...
- Java值传递和引用传递
Java总是在讨论是传递还是引用传递,Java没有像C语言那样拥有指针,在看到引用传递和值传递很多的解释之后,更相信引用传递和值传递归根到底都是值传递,只不过引用传递的时候看上去很高大上,其实是把变量 ...
- java基本数据类型传递与引用传递区别
文章转载自 zejian的博客http://blog.csdn.net/javazejian/article/details/51192130 java的值传递和引用传递在面试中一般都会都被涉及到, ...
随机推荐
- SpEL + AOP实现注解的动态赋值
一.自定义注解 先聊聊这个需求,我需要根据用户的权限对数据进行一些处理,但是痛点在哪里呢?用户的权限是在请求的时候知道的,我怎么把用户的权限传递给处理规则呢?想了以下几种方案: Mybatis 拦截器 ...
- 基于R数据分析之常用Package讲解系列--1. data.table
利用data.table包变形数据 一. 基础概念 data.table 这种数据结构相较于R中本源的data.frame 在数据处理上有运算速度更快,内存运用更高效,可认为它是data.frame ...
- 五分钟学会HTML5的WebSocket协议
1.背景 很多网站为了实现推送技术,所用的技术都是Ajax轮询.轮询是在特定的的时间间隔由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器.这种传统的模式带来很明显的缺点 ...
- Python3安装mysql模块
pip3 install mysql 1.错误1 原因:在 Python 3.x 版本后,ConfigParser.py 已经更名为 configparser.py 所以出错! 解决,将模块cp一份为 ...
- linux目录数
FHS Filesystem Hierarchy Standard(文件系统层次化标准,[ˈhaɪərɑ:rki] 等级制度)的缩写,多数Linux版本采用这种文件组织形式,类似于Windows操作系 ...
- 阿里云ECS服务器部署HADOOP集群(二):HBase完全分布式集群搭建(使用外置ZooKeeper)
本篇将在阿里云ECS服务器部署HADOOP集群(一):Hadoop完全分布式集群环境搭建的基础上搭建,多添加了一个 datanode 节点 . 1 节点环境介绍: 1.1 环境介绍: 服务器:三台阿里 ...
- 从surfaceflinger历史变更谈截屏
众所周知,有一个程序screencap可以截屏,这个程序十分简单,只是使用了surfaceflinger服务的截屏功能. 所以要了解截屏,看surfaceflinger服务的代码是不二首选.但是sur ...
- react-router-dom路由
- GeoServer 安装教程
准备内容 安装环境:win10*64位专业版 安装文件:geoserver-2.15.2 安装步骤 安装JDK 1.安装GeoServer是基于Java的环境,所以需要先装Jdk环境. 2.前往官网下 ...
- LMS自适应天线阵列设计 MATLAB
在自适应天线课上刚刚学了LMS自适应阵,先出一个抢先版贴一下结果,抢先某个小朋友一步. 关于LMS的具体介绍,直接看wiki里的吧,解释的比书上简明:传送门:https://en.wikipedia. ...