[转载] java中对象作为参数传递给一个方法,到底是值传递,还是引用传递
参考链接: 用Java传递和返回对象
看完绝对清晰~
java中对象作为参数传递给一个方法,到底是值传递,还是引用传递?
pdd:所谓java只有按值传递:基本类型 值传递;引用类型,地址值传递,所以叫值传递。
当主函数的变量,对象(主本)传递到副函数时,传递的变量、对象(方法中的形参)其实都是副本,而副本的改变不会影响主 本。
基本类型:传递的是值的拷贝,也就是说传递后就互不相关了,也就是说,不过副函数的副本如何变化,主本永远不会被影响。
引用类型:传递的是引用地址值,有可能会被影响。
string:具有不可变。是特殊的引用类型,其作用跟基本类型一样,传递后不相关。
原作者:
String和int参数传递是按值传递还是引用传递?
一道面试题目,String的传递:
1 2 3 4 5 6 7 8 9 public String change(String s){ s = "222"; return s; } public static void main(Stirng[] args){ String s = "111"; change(s); sout(s); }
我看到题目愣了一下,本来不假思考的结果是111,但仔细想,String是对象类型的,对象传递的是地址,那么地址传递到方法里面后,将指向修改成222,那么结果应该是222才对。实际恰恰相反。
Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本。指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)是永远不会改变的。
java传递参数都是值,如果是对象的话,就是将引用的值复制一份给方法当参数。如果是根据引用把堆里的对象修改了,那么对象真被修改了,不过不是被创建赋值给的那个引用修改的,是方法里的一个复制的引用副本给修改的。换句话说,施瓦星格的媳被施瓦星格的克隆人亲了下。
用实例去理解,其实这个理解也就是根据jdk的结果告诉我自己记住规则是这样的,以后要记住。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public String change(String s, int i, StringBuffer sb, Person p){ s="123"; i=3; sb.append("woshi"); p.setAge(100); sb = new StringBuffer("sbsb"); p = new Person("bb",44); return s; } @Test public void testChange(){ StringBuffer sb = new StringBuffer("buff"); String s = "aaa"; int i = 1; Person p = new Person("aa",12); i=2; change(s,i,sb,p); // s="222"; System.out.println(s); System.out.println(i); System.out.println(sb.toString()); System.out.println(p); }
这里一共测试了String,int,一个对象StringBuffer,一个对象people。让我们来仔细看看这些传递都发生了什么。我想有很大一部分人都猜不出打印结果。
1 2 3 4 aaa 2 buffwoshi Person{id=0, name='aa', age=100, Country=null, hashcode=638783031}
我们来一个个分析。
首先是String。
1 String s = "aaa";
这里,jvm创建一个变量引用s,在堆中创建一个对象aaa,将aaa放进常量池。s指向aaa。
然后就到了change方法里。这里这样理解:将s引用的一个拷贝传给方法change。这样change有一个变量s,这个s也是指向aaa的。那么我们来通过debug来看后来发生了什么。
1.s指向aaa的时候:
2.s运行到change方法里的时候
然后看s再次赋值的时候:
然后我们运行结束change方法后到主方法里:
到这里s就结束了。那么如果我们按照传递的是s这个变量的引用,即String s="aaa"中这个s本身,那么,s这个本身是个变量,s指向aaa,在方法change里s又指向了123,回到主方法后s变量的指向被改变了?错!显然s仍旧是aaa,那么只能这样理解:s传递到方法里的时候,复制了s指向的地址给change,change里的s是另一个s,s指向aaa(@718),然后在change中s又指向了123(@731),由于String是不可变类(final and Immutable),这里只是把副本s的指向修改成731,原地址718里的对象没有发生改变因为String不可变。那么,回到主方法的时候,s变量本身没有任何改变,s仍旧指向地址718,718的内容是aaa。所以最终打印aaa。
然后是StringBuffer
int是基本类型,所以int只是将值复制一份给别的方法用,这个大家都知道,就不去测试了。现在看StringBuffer发生的改变。
1.初始化:
2.到change方法中:
3.发生append
4.指向新对象
这里就要说一下了,副本指向了新对象。就好比,施瓦星格的克隆人找了另一个女的当老婆,而真正的施瓦星格老婆没有变。
5.回到主方法:
到这里,StringBuffer就结束了。我们必须知道,虽然我们没有去研究源码是怎样实现的,change方法得到是一个sb的副本,只不过这个副本指向708,在change里对708的对象追加,708的对象就真的改变了。然后又把sb副本指向新地址737。这只是把副本指向的地址修改了,如果你在这里打印sb.toString(),打印的就是737里的内容。当跳出change,回到主方法的时候,原sb仍旧还是指向708的,最终就是打印708的结果。和String不同的是,StringBuffer的结果发生了变量,因为StringBuffer是可变的,可以append。而String是不可变的,在change中s=123就是发生两个行为,一个是查找常量池中是否有123,如果没有就在堆中创建123,一个是将s指向123.也就是说这时候是创建了一个新的String对象,而不是把原来的String对象s内容修改。这样,回到主方法的时候,s仍旧是aaa。
同理,看自己创建的对象people
1.初始化:
2.p传递到change里的时候
3.p副本设置age
4.p副本重新赋值
这里仍旧要说一下,p副本修改了自己指向,并不影响主方法里的p的指向。主方法里的p的指向没有发生变化,依旧应该还是720.
5.回到主方法
总结:
通过上面对String,StringBuffer,People的研究,应该明白一个道理,重要的话说三遍,重要的规则我都演示了三遍。如果跟着步骤一步步走的,肯定牢记住了:
java所有的参数传递都是传递的副本,变量所代表的值的副本!java所有的参数传递都是传递的副本,变量所代表的值的副本!java所有的参数传递都是传递的副本,变量所代表的值的副本!
这里必须记住的就是副本概念。在方法里,运行的时候到这里的线程都会把传过来的参数拷贝副本带自己的工作区中,在工作区中对这个副本的值发生一些改变。最终改变的是副本,如果通过副本的指向修改了指向中的内容,那么那个指向的地址里的内容确实改变了。如果修改了副本的指向,即给副本重新赋值,那么关原来的变量何事?元变量仍旧指向最初的地址。
那么,String传递过去的是副本,修改了副本的指向,打印元string是不会改变的,因为副本没有能力修改final的String类。
出处:http://blog.csdn.net/zzp_403184692/article/details/8184751
[转载] java中对象作为参数传递给一个方法,到底是值传递,还是引用传递相关推荐
- [转载] Java中对象数组的使用
参考链接: 如何在Java中交换或交换对象 Java对象数组使用 一.Java数组的使用二.Java的对象数组2.1 问题提出2.2 问题解析2.3 问题拆分2.4 代码实现 一.Java数组的使用 ...
- java参数传递:值传递还是引用传递
2019独角兽企业重金招聘Python工程师标准>>> 基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的: 在Java中对象作为参数传递时,是把对象在 ...
- 【重难点】【Java基础 04】值传递和引用传递、序列化和反序列化
[重难点][Java基础 04]值传递和引用传递.序列化和反序列化 文章目录 [重难点][Java基础 04]值传递和引用传递.序列化和反序列化 一.值传递和引用传递 1.对比 二.序列化 1.基本概 ...
- java面试题:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
java面试题:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递.Java编程语言只有值传递参数. 当一个对象实 ...
- Java中对象和引用的理解
2019独角兽企业重金招聘Python工程师标准>>> 偶然想起Java中对象和引用的基本概念,为了加深下对此的理解和认识,特地整理一下相关的知识点,通过具体实例从两者的概念和区别两 ...
- Java中,String类型和包装类型作为参数传递时,是属于值传递还是引用传递呢?...
<Java中,String类型和包装类型作为参数传递时,是属于值传递还是引用传递呢?> <Java中的值传递和引用传递> 原理知识: 如果参数类型是原始类型,那么传过来的就是这 ...
- Java中的参数传递,到底是值传递还是引用传递?
文章内容为转载,转载自公众号Hollis关于我要彻底给你讲清楚,Java就是值传递,不接受争辩的那种! 原文链接:我要彻底给你讲清楚,Java就是值传递,不接受争辩的那种! 知乎回答链接:Java 到 ...
- 浅析Java中对象的创建与对象的数据类型转换
这篇文章主要介绍了Java中对象的创建与对象的数据类型转换,是Java入门学习中的基础知识,需要的朋友可以参考下 Java:对象创建和初始化过程 1.Java中的数据类型 Java中有3个数据 ...
- Java中对象的三种状态
转载自 Java中对象的三种状态 Java中的对象的三种状态是和垃圾回收紧密相关的,因此有必要深究. 状态一:可触及态:从根节点开始,可以搜索到这个对象,也就是可以访问到这个对象,也有人将其称为可 ...
最新文章
- 设计模式之C#实现---- ProtoType
- Git环境搭建及简单的本地、远程 两库关联
- Spring Cloud(八)高可用的分布式配置中心 Spring Cloud Config
- IE浏览器Cookie信息提取工具Galleta
- 防火墙双机热备三大协议(VRRP-VGMP-HRP)原理
- 李开复给中国学生的第六封信:选择的智慧
- 利用计算机漏洞犯罪,利用漏洞非法谋利2000元怎么处罚
- Ubuntu 下安装LEMP环境 实战
- (7)MySQL的事务
- 用 RxSwift 实现通用的响应式转场
- Ineedle驱动方式dpdk测试性能
- vue 一个页面多个router-view如何配置子路由_浅谈vue前端开发架构
- mysql必知必会心得_SQL必知必会知识总结
- 使用readelf和objdump剖析目标文件
- STM32多个串口重定义
- 普华永道:2030年区块链价值将突破30万亿
- python怎么过验证_Python3基础:如何验证你的代码
- Linux配置本地yum源(光盘镜像挂载)
- python爬取招聘网站视频教程_Python爬取拉钩招聘网
- MarkdownPad 2使用教程(语法篇)
热门文章
- 【Luogu1182】数列分段Section II(二分)
- mysql优化教程_Mysql优化一
- python mainloop作用_Tkinter中的mainloop应该如何理解?
- JavaScript数据类型之字符串型(4)
- excel换行按什么键_电脑黑屏按什么键恢复 电脑黑屏的原因和恢复方法
- bzoj 4895: 项链分赃(增强版)
- python实现一个简单的【图像中物体坐标】标注小工具
- python计算两张图像的L1和L2损失
- python聊天机器人
- java list循环_【知识】Java中循环打印出LIST的各属性的值