• 克隆


    为什么要克隆

    package algorithm;
    
    public class Person {
    
    	private String name;
    
    	public Person() {
    	}
    
    	public Person(String name) {
    		this.name = name;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String toString(){
    		return "name="+name;
    	}
    }
    
    public class Test{
      public static void main(String[] args) throws Exception { Person person1 = new Person("a"); System.out.println("person1:"+person1); Person person2 = person1; System.out.println("person2:"+person2); System.out.println("person2中name修改为b"); person2.setName("b"); System.out.println("person1:"+person1);   }
    }

     person1:name=a
    person2:name=a
    person2中name修改为b
    person1:name=b

    这就是没有克隆出现的问题,因为只是引用的赋值,它们指向同一对象,如果一个修改另一个也会影响。所以我们需要克隆一个对象,让它们指向不同的对象。

    Object的clone()被声明为proctected,那么根据http://www.cnblogs.com/tp123/p/6406576.html中对protected的描述,可以知道我们想要某个类使用clone方法,就必须在该类中重写clone方法(否则就只能在该类中调用)。

    对于上面的就是在Person里面可以通过this.clone()或super.clone(),new Person().clone()来调用,但是在Test中就不可以通过Person person1 = new Person("a");person1.clone();Test自身也是可以调用。

    但是要求调用clone方法的对象必须实现cloneable,如果没有实现该接口就会报错。

    所以一般要使用clone方法

    1.实现cloneable接口,表示这是一个可clone的对象。

    2.重写一个public的clone方法。
     

     克隆的例子

    package algorithm;
    
    public class Person implements Cloneable{
    
    	private String name;
    
    	public Person() {
    		System.out.println("执行person的构造方法");
    	}
    
    	public Person(String name) {
    		this.name = name;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public Person clone() throws CloneNotSupportedException {
    		return (Person)super.clone();
    	}
    
    	public String toString(){
    		return "name="+name;
    	}
    	
    }
    
    public static void main(String[] args) throws Exception{
    		Person p1 = new Person();
    		p1.setName("person1");
    		System.out.println("p1:"+p1);
    		Person p2 = p1.clone();
    		System.out.println("p2:"+p2);
    		p2.setName("person2");
    		System.out.println("p2修改后");
    		System.out.println("p1:"+p1);
    		System.out.println("p2:"+p2);
    	}
    

     结果

    执行person的构造方法
    p1:name=person1
    p2:name=person1
    p2修改后
    p1:name=person1
    p2:name=person2
    

     从结果可以看出

    1.java克隆调用的根本还是Object的克隆方法。

    2.clone方法并没有调用构造方法。(因为只有一次调用构造方法,是new的时候调用的)。     clone方法是一个native方法,应该是c++直接内存复制产生一个新对象。

    3.调用clone方法确实产生了新的对象,所以修改person2的内容不会修改person1。

    浅克隆和深克隆

    1.浅克隆,就是表层的克隆,也就是只对最外层的对象进行克隆,而里面的所有引用的对象并没有克隆,只克隆了这些对象的地址。

    2.深克隆,就是除了克隆自己也克隆所有里面的对象实例。

    如果要深克隆,有两种办法。

    1.对对象序列化,然后反序列化。

    2.先调用super.clone()方法克隆出一个新对象来,然后在子类的clone()方法中手动给克隆出来的非基本数据类型(引用类型)赋值。

  • 相关阅读:
    Ubuntu16.04下安装virtualbox,配置及卸载
    机器学习1-线性回归
    python中的数据结构-链表
    Numpy 对于矩阵的操作持续更新
    ubuntu16.04 下同时打开多个终端窗口
    matlab mashgrid 函数
    站立会议04
    站立会议03
    第一次冲刺--站立会议02
    第一次冲刺--站立会议01
  • 原文地址:https://www.cnblogs.com/tp123/p/6403067.html
Copyright © 2020-2023  润新知