解惑4:java是值传递还是引用传递
一、概述
曾经纠结了很久java的参数传递方式是什么样的,后面粗略的了解了一鳞半爪以后有了大概的印象:“传参数就是值传递,传对象就是引用传递”,后面进一步查找了相关资料和文章以后,发现这么理解是不正确的。
这里先放结论:
- java中参数的传递可以理解为都是值传递
 - 基础数据类型传递的是值的拷贝
 - 对象类型是共享对象传递,传递的是地址的拷贝
 
二、形参和实参
要理解参数的传递就必须先理解形参和实参:
形参:就是形式参数,用于定义方法的时候使用的参数,是用来接收调用者传递的参数的。
形参只有在方法被调用的时候,虚拟机才会分配内存单元,在方法调用结束之后便会释放所分配的内存单元。
因此,形参只在方法内部有效,所以针对引用对象的改动也无法影响到方法外。
实参:就是实际参数,用于调用时传递给方法的参数。
举个例子:
public static void main( String[] args ) {
    String string = "Hello";
    //string是实际参数
    sout(string);
}
public static void sout(String str){
    //str为形式参数
    System.out.println(str);
}
三、值传递和引用传递与共享对象传递
1.值传递和引用传递
理解了实参和形参,以及java对应的数据类型,我们就可以理解值传递和引用传递了。
值传递:方法调用时,实际参数的值被传递给对应的形式参数,函数接收的是原始值的一个copy, 此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值。
引用传递/址传递:方法调用时,实际参数的地址被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址。在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。
对于这两种方式,网上有一个非常形象的图:

2.共享对象传递
但是java的传值策略有点类似于两者的结合,是共享对象传递:
- 共享对象传递:先获取到实际参数的地址,然后将其复制,并把该地址的拷贝传递给被调函数的形式参数。因为参数的地址都指向同一个对象,所以我们称也之为"传共享对象",所以,如果在被调函数中改变了形式参数的值,调用者是可以看到这种变化的。
 
这也是之所以说java也是值传递的原因,共享对象传递实际上也是对实参进行拷贝然后赋给形参,但是操作针对的对象不是值而是地址!
由于传递的是地址的拷贝,所以如果你在方法中将这个地址指向了新的对象,实际上是没有任何对方法外是没有任何作用的,举个例子:
public static void main( String[] args ) {
    Person p = new Person();
    System.out.println("main中:" + p.hashCode());
    change(p);
    System.out.println("main中:" + p.hashCode());
}
public static void change(Person person){
    person = new Person();
    System.out.println("change中:" + person.hashCode());
}
//输出
main中:692404036
change中:1554874502
main中:692404036
可以看到在main方法中输出的hashCode指向的都是同一个对象,而change中指向了另一个,可以这么理解:
- p为指向了第一个Person对象的地址
 - 把p拷贝了一份得到p‘,这里的p’就是
change方法中的形参p change中p指向了一个新的Person对象,在change这个函数范围里p指向的就是new出来的第二个Person对象的地址- 由于
change中的p实际上是main中p的拷贝p‘,所以在change里p'指向的改变对main中的p不会有任何影响 
四、总结
你在福建有座仓库,给自己配了一把钥匙
1.三种传递:
- 值传递:你建了一座一模一样的仓库给别人
 - 引用传递:把你家仓库的钥匙给了别人
 - 共享对象传递:把你家仓库钥匙复刻了一把给别人
 
2.共享对象传递的特点:
- 拷贝的地址与原地址指向同一个内存对象:别人用你复刻的钥匙一样能进出你的仓库
 - 拷贝地址引用对象的改变不影响原地址的引用对象:别人在山东也盖了个仓库,用你给他的钥匙配了锁,他的钥匙在山东只能开他的仓库,你的钥匙在福建只能开你的仓库
 
解惑4:java是值传递还是引用传递的更多相关文章
- Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义
		
一.Java中什么叫做引用类型变量?引用:就是按内存地址查询 比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...
 - java中值传递和引用传递
		
最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...
 - Java中的值传递和引用传递
		
这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...
 - java的值传递和引用传递
		
昨天博主在对于值传递和引用传递这里栽了一个大坑啊,导致一下午时间都浪费在这里,我们先说下值传递和引用传递java官方解释: 值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对 ...
 - java中方法的参数传递机制(值传递还是引用传递)
		
看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递.Java 编程语言只有值传递参 ...
 - java 对象传递 是 值传递 还是 引用传递?
		
这个问题说实话我感觉没有太大的意义. 按第一印象和c++的一些思想去理解的话对象传递是引用传递,因为传递过去的对象的值能被改变. 但是又有很多人,不知道从哪里扣出来一句,java中只有值传递,没有引用 ...
 - java参数传递时到底是值传递还是引用传递
		
java参数传递时到底是值传递还是引用传递(baidu搜集) 问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解. 原题是:当一 ...
 - Java面向对象-方法的值传递和引用传递
		
Java面向对象-方法的值传递和引用传递 0 发布时间:『 2016-08-21 14:21』 博客类别:Java核心基础 阅读(197) 评论(0) Java面向对象-方法的值传递和引用传递 方 ...
 - Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结
		
这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...
 
随机推荐
- MCU 51-5中断
			
中断概念 : 计算机执行某程序时,发生了紧急事件或有特殊请求,CPU暂停某程序的执行, 转而去处理上述事件或请求,处理完毕后再重新执行某程序的过程叫做中断. 数据的输入/输出传送方式: (1)无条件传 ...
 - python面试题七: mysql数据库
			
---------------------------------------------------------------------------------------------------- ...
 - CodeChef Sum of distances(分治)
			
CodeChef Sum of distances(分治) 题目大意 有一排点,每个点 i 向 \(i + 1, i + 2, i + 3\) 分别连价值为 \(a_i,b_i,c_i\) 的有向边, ...
 - mysql中常见约束
			
#常见约束 /* 含义:一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性 分类:六大约束 NOT NULL:非空,用于保证该字段的值不能为空 比如姓名.学号等 DEFAULT:默认,用于 ...
 - android 调试的一些问题解决1
			
1.系统自带的机器跑起来太卡,我想用雷电模拟器来运行.可是打开后找不到设备怎么弄? 解决办法: 步骤1:>>>运行模拟器 步骤2:>>>win + r 打开cmd ...
 - Python 为什么用 # 号作注释符?
			
关于编程语言中的注释,其重要性基本上已为大家所共识. 然而关于注释的规范,这个话题就像我们之前聊过的缩进.终止符和命名方式一样,众口难调. 注释符通常可分为两种,即行注释与块注释(inline/blo ...
 - Makefile中自动生成头文件依赖
			
为什么需要自动生成头文件依赖? 编译单个源文件时,需要获取文件中包含的头文件的信息,但是一般的Makefile不会在规则中明确写明文件依赖的头文件,所以单独修改头文件后,不会导致包含头文件的源文件重新 ...
 - 题解 洛谷 P3571 【[POI2014]SUP-Supercomputer】
			
由数据范围可得出,不可能一次一次去进行回答询问,只能离线处理,然后\(O(1)\)解决. 考虑\(DP\)解决,先给出\(DP\)方程: \(f_i=max(j+ \lceil \frac{s_{j+ ...
 - phpMyAdmin历史漏洞复现
			
简介 phpMyAdmin是一个非常受欢迎的基于web的MySQL数据库管理工具.它能够创建和删除数据库,创建/删除/修改表格,删除/编辑/新增字段,执行SQL脚本等 复现三个古老漏洞 phpMyAd ...
 - Spring Security 实战干货:从零手写一个验证码登录
			
1. 前言 前面关于Spring Security写了两篇文章,一篇是介绍UsernamePasswordAuthenticationFilter,另一篇是介绍 AuthenticationManag ...