在Java中,当对象做为参数传递时,究竟传递的是对象的值,仍是对象的引用,这是一个饱受争议的话题。若传的是值,那么函数接收的只是实参的一个副本,函数对形参的操做并不会对实参产生影响;若传的是引用,那么此时对形参的操做则会影响到实参。
首先咱们来看一句代码:app
Object obj = new Object();
这句话的意思是:建立一个Object对象,再建立一个名为obj的引用,让这个引用指向这个对象,以下图所示:函数
在有了上面的基础以后,咱们便来看下面这组在网上很流行的例子:spa
例1:.net
public class test { public static void main(String[] args) { int i = 1; System.out.println("before change, i = "+i); change(i); System.out.println("after change, i = "+i); } public static void change(int i){ i = 5; } }
这个例子不难理解,当基本数据类型(Boolean,byte,char,String,int,Long,float,double)做为参数传递时,传递的是实参值的副本,即传的是值,不管在函数中怎么操做这个副本,实参的值是不会被改变的。因此以上代码执行的结果是:
3d
before change, i = 1
after change, i = 1
在下面的例2中,咱们把StringBuffer对象做为参数传递到change函数。
例2:code
public class test { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("before change, sb is "+sb.toString()); change(sb); System.out.println("after change, sb is "+sb.toString()); } public static void change(StringBuffer stringBuffer){ stringBuffer.append("world !"); } }
为了方便推理出结论,咱们先直接看程序的运行结果:
对象
before change, sb is Hello
after change, sb is Hello world !
从输出结果中咱们能够发现,sb所指向的对象的值被改变了,那么是否咱们能够推论出,在Java中,当对象做为参数传递时,传递的是该对象的引用呢?咱们再来看下面这个例子: blog
public class test { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("before change, sb is "+sb.toString()); change(sb); System.out.println("after change, sb is "+sb.toString()); } public static void change(StringBuffer stringBuffer){ stringBuffer = new StringBuffer("Hi "); stringBuffer.append("world !"); } }
若是上面的推论是正确的,即Java中对象做为参数传递,实际传递的是该对象的引用,那么在调用change函数以后,原对象的值应该是会改变的,变为“Hi world !”,可是,当咱们运行程序后,结果倒是以下所示:
内存
before change, sb is Hello
after change, sb is Hello
原对象的值并无被改变,这与上面的推论相矛盾!为何在Java中,当对象做为参数传递时,有的时候实参被改变了,而有的时候实参并未被改变呢?下面让咱们来分析一下其中的缘由:
从文章的开头咱们知道,当执行StringBuffer sb = new StringBuffer(“Hello “)时,咱们建立了一个指向新建对象“new StringBuffer(“Hello “)”的引用“sb”,以下图所示: string
在例2中,当咱们调用change函数后,实际上,形参stringBuffer也指向了实参sb所指向的对象,即:
那么当咱们执行stringBuffer.append(“world !”)后,便经过对象的引用“stringBuffer”修改了对象的值,使之变成了“Hello world !”,即:
可是,在例3中的change函数中,咱们又新建了一个对象“new StringBuffer(“Hi “)”(这实际上在内存中开辟了一块在原对象地址以外的新区域),这让形参stringBuffer实际指向了这个新建的对象,并将新对象的值设置为“Hi world !”,例三中stringBuffer的值已经被改变为了Hi world,可是由于值没有被return返回赋值给sb对象,因此sb对象并无被改变,因此输出的任然是hello,即:
那么咱们就不难理解,为什么在执行完change函数以后,实参的值仍为“Hello”了。
综上所述,咱们能够得出结论:在Java中,当对象做为参数传递时,实际上传递的是一份“引用的拷贝”。 (实际传递的是对象的引用)
转载自:https://blog.csdn.net/xiangwanpeng/article/details/52454479