(四)引用传递、值传递、clone

一、引用传递和值传递
引用传递有两种方式:①通过函数的参数进行传递②=

public class Obj {

	private String str="default value";

	public String getStr() {
		return str;
	}

	public void setStr(String str) {
		this.str = str;
	}
	
	public String toString(){
		return str;
	}
	
	public static void main(String[] args) {
		Obj obj=new Obj();
		System.out.println(obj);  //输出对象时,会自动调用toString方法
		Obj obj2=obj;
		obj2.setStr("change value");
		System.out.println(obj);
		System.out.println(obj2);
	}
}
输出:
default value
change value
change value

public class TestRef {
/*
 * Java基本数据类型:数值类型byte、short、int、long
 *                 浮点类型float、double
 *                 字符类型char
 *                 布尔类型boolean 
 */
	private Obj obj=new Obj();
	private int a=0;
	public Obj getObj() {
		return obj;
	}
	public void setObj(Obj obj)
	//obj=ref.getObj 引用传递 相当于指向同一对象,所以当obj对象内容改变,ref的obj对象也发生改变
	{
		obj.setStr("changed value");
	}
	public int getA() {
		return a;
	}
	public void setA(int a)
	//a =0 值传递,传递的是输入参数的复制,注意两个a并不相同
	{
		a=1;
	}
	
	public static void main(String[] args) {
		TestRef ref=new TestRef();
		System.out.println("引用数据类型");
		System.out.println(ref.getObj());
		
		ref.setObj(ref.getObj());//
		System.out.println(ref.getObj());
		
		System.out.println("基本数据类型");
        System.out.println(ref.getA());
		
		ref.setA(ref.getA());
		System.out.println(ref.getA()); 
		
	}
	
}

输出:
default value
changed value
基本数据类型
0
0

为什么Obj是对基本数据类型值改变,两个对象的值都改变;而TestRef就不能改变呢?
因为Obj中的setStr 中this.name="change value" 
     TestRef里面是 a=1

二、clone
在实际编程中,经常会根据已有的对象A创建出另一个与A具有相同状态的对象B,并且对B的修改不会影响到A的情况。
在这里插入图片描述例子见:https://www.cnblogs.com/acode/p/6306887.html
浅拷贝(Shallow Copy):
①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。
**具体模型如图所示:**可以看到基本数据类型的成员变量,对其值创建了新的拷贝。而引用数据类型的成员变量的实例仍然是只有一份,两个对象的该成员变量都指向同一个实例。
在这里插入图片描述深拷贝:首先介绍对象图的概念。设想一下,一个类有一个对象,其成员变量中又有一个对象,该对象指向另一个对象,另一个对象又指向另一个对象,直到一个确定的实例。这就形成了对象图。那么,对于深拷贝来说,不仅要复制对象的所有基本数据类型的成员变量值,还要为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象图进行拷贝!

简单地说,深拷贝对引用数据类型的成员变量的对象图中所有的对象都开辟了内存空间;而浅拷贝只是传递地址指向,新的对象并没有对引用数据类型创建内存空间。
深拷贝模型如图所示:可以看到所有的成员变量都进行了复制。
在这里插入图片描述String类型非常特殊,所以我额外设置了一个字符串类型的成员变量来进行说明。首先,String类型属于引用数据类型,不属于基本数据类型,但是String类型的数据是存放在常量池中的,也就是无法修改的!也就是说,当我将name属性从“摇头耶稣”改为“大傻子"后,并不是修改了这个数据的值,而是把这个数据的引用从指向”摇头耶稣“这个常量改为了指向”大傻子“这个常量。在这种情况下,另一个对象的name属性值仍然指向”摇头耶稣“不会受到影响。

posted @ 2019-01-26 17:29  测试开发分享站  阅读(100)  评论(0编辑  收藏  举报