关于Clone克隆对象的讲解

来源:互联网 发布:黑暗之魂淘宝 编辑:程序博客网 时间:2024/05/16 09:48

本人以前被问到有哪些方法创建对象

我回答,new,反序列化,反射。后来才知道还有个克隆(汗颜哭

克隆clone,这个方法我经常在object类中看到,之前也一直没关注过它,直到最近看克隆的时候才开始关注

什么是克隆?

这得先讲解下new一个对象的原理,简单来说就是先在内存中分配一个对象(所要new的对象)大小的内存,然后通过构造方法往这个内存里面注入值,然后这个对象的引用

而clone与new相似,也是先在内存中分配一个对象大小的内存,然后根据原对象的值赋值给新对象。然后返回这个对象的引用

而要实现clone必须重写Object类中的clone方法,且实现Cloneable否则报CloneNotSupportedException异常。这个接口是个标记接口,即使接口内部没有任何方法

而clone克隆又分浅拷贝和深拷贝

浅拷贝的意思是简单的赋值数据,而不重新开辟新的对象,super.clone()直接调用这个方法为浅拷贝

深拷贝的意思的,先开辟对象在从原来对象中获取数据,赋值给新开辟的对象中

public class Person implements Cloneable{public String name;public int age;/** * public 开放权限,从object继承过来是protected * 若是类中有对象属性,应该实现深拷贝(先开辟对象在复制值),类中只有简单类型则直接调用父类super.clone() */@Overridepublic Object clone() throws CloneNotSupportedException {/* * 1、执行super.clone()方法   先从内存中开辟一个对象的空间, * 在从原来对象中赋值给该对象,简单值传递。传递引用变量,这意味着都是浅拷贝 * 这就意味着原来的对象的复杂类型的值发生改变则clone的对象里面的相同属性也将发送改变 * 2、但是String除外String是无法改变对象内值的复杂类型, * String类型发送改变也只是在内存中新创建一个字符串对象,将该对象的引用返回而原字符串还存在内存中! *  */Person person = (Person)super.clone();//返回一个浅拷贝的对象person.name = new String(((Person)super.clone()).name);//手动new出新的对象出来并且赋值 //实际上String类型并不需要new一个新对象,因为无法改变String的值,所以无法导致原数据的改变而影响现在数据return person;}public Person(String name, int age) {this.name = name;this.age = age;}}

//需要克隆的对象必须实现Cloneable接口,否则报CloneNotSupportedExceptionpublic class School implements Cloneable{public Person person;public int number;/** * 实现克隆的对象中如果有其他类的对象,需要调用其他类的clone方法 */@Overridepublic Object clone() throws CloneNotSupportedException {School school = (School)super.clone();school.person = (Person)person.clone();return school;}public School(Person person, int number) {this.person = person;this.number = number;}}

public class CloneTest {public static void main(String[] args) {Person p = new Person("wxt",12);try {Person p1 = (Person) p.clone();System.out.println(p1==p);// false  不是相同对象System.out.println(p1.name.equals(p.name));  //true 值相同System.out.println(p1.name==p.name);  //false  name属性不是相同对象} catch (CloneNotSupportedException e) {e.printStackTrace();}/************************************/System.out.println("/************************************/");// false  不是相同对象School school = new School(p,55);try {School s1 = (School)school.clone();System.out.println(school==s1);                         // false  不是相同对象System.out.println(school.person.name.equals(s1.person.name));  //true person属性的name值相同System.out.println(school.person==s1.person);            //false  person属性不是相同对象} catch (CloneNotSupportedException e) {e.printStackTrace();}}}