Java对于赋值,浅拷贝,深拷贝的原理理解以及深入思考

Java对于赋值,浅拷贝,深拷贝的原理理解以及深入思考

对于基础数据类型赋值:
	至少在java中而言(经过资料查找以及测试),对于基础类型的赋值,例如 int a=3,int b=3,int c=a。
	1. 首先a作为基础数据类型而又是局部变量的情况下会保存在常量池(栈中)。(String 类也可以保存在栈中,类似于基础数据类型赋值方式而不用new创建对象实例,例如 String a="aaa";,赋值方式类似以下)。
	2. b=3这一步会首先检索常量池中是否已经有了3,如果已经存在3,那么会将指针指向已存在的3的位置,此时相当于a,b同时指向一个3.
	3. c=a这一步显然ac是指向同一个3,但是如果直接改变c的值。例如让c=2,这时并不会改变a的值,而是会像 2.一样操作。
	
如果是对于对象的赋值,例如:
		Object b = new Object();
		Object a = b;
		在赋值只是将a指向了堆中的b对象的位置,整个过程只创建(new)了一个对象使得a去改变也会改变b。
		
在阅读一些文档后可以得知,基础数据类型也就是值类型,保存在stack(栈)中,对象的类型为引用类型,即对象本身保存在heap(堆)中,而对象的引用(例如变量b本身)保存在stack中,是存储了对象本身在heap中的位置信息。


浅拷贝:
定义是:如果原型对象的成员变量是值类型,将复制一份给克隆对象,也就是说在堆中拥有独立的空间;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

个人理解是,因为浅拷贝是针对一个对象拷贝,而一个对象中是可能存在值类型(即基础数据类型的变量)和引用类型。浅拷贝对于值类型 如:int,char,则复制一份给拷贝对象。
而对于引用数据类型,则会拷贝地址给拷贝对象,即两个对象中的引用类型的变量地址是一样的,其中一个做出改变,另一个也会改变。但是对于特殊的一些情况,如String、Integer,这两个本身也是类,但是因为他们是不可改变类,当修改不可改变类的值时,会重新在堆中创建一个新的对象。所以如果是对于不可改变类,在其中一个中改变,另一个并不会被改变,这个倒有点像栈中的赋值操作。
实现方法是:首先使被拷贝对象实现Cloneable接口(implements Cloneable),然后重写*父类Object中的clone方法,直接return super.clone();

深拷贝:
就是完全创建一个新实例,new一个新对象,拷贝对象与原对象完全不相干,属于是独立于原对象。
深拷贝方法有两种,一种类似浅拷贝,但是对于重写clone方法时不能简单调用super中的clone,而是将其中的引用对象也克隆一次(唯一区别)。
如:
@Override
public Object clone() throws CloneNotSupportedException {
        Person person = (Person)super.clone();
        // 然后需要将引用对象也克隆一次
        person.personDesc = (PersonDesc) 				personDesc.clone();
        return person;
    }
还有一种是将对象序列化,类似于首先将整个对象内容转化成一串代码,然后将这串代码克隆。前提是将对象使实现序列化接口Serializable。具体的操作略
上一篇:Java 浅拷贝和深拷贝的理解和实现方式


下一篇:Java 设计模式——原型模式(创建型设计模式)