Java中的Clone

Java Clone

1.克隆的概念
    A:
浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。 

   注:Object类里的clone方法是浅复制(浅克隆)
    B:
深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍。 

   C: Clone的公约
        1. x.clone() != x // x.clone() will return a new object

        2. x.clone().equals(x) // this is the meaning of ‘copy’

        3. x.clone().getClass() == x.getClass() 


        4. The object returned by clone method should be independent of the object (which is  
            being cloned).

 

 

 

      These are not absolute requirements but are general intends of clone method which is also recommended in Java

        Documents.

2.对象克隆的两种方式
A.我们可以利用Object类的clone()方法,必须要遵循下面三点 
     (1)
在派生类中覆盖基类的clone()方法,并声明为public Object类中的clone()方法为protected的】。 
     (2)
在派生类的clone()方法中,调用super.clone() 
     (3)
在派生类中实现Cloneable接口。

     被克隆的类必须自己实现Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。Cloneable 接口实际上是个标识接口,没有任何接口方法。实现Cloneable接口的类应该使用公共方法重写 Object.clone(它是受保护的)。某个对象实现了此接口就克隆它是不可能的。即使 clone 方法是反射性调用的,也无法保证它将获得成功。在Java.lang.Object类中克隆方法是这么定义的:

protected Object clone()  throws CloneNotSupportedException

创建并返回此对象的一个副本。表明是一个受保护的方法,同一个包中可见。按照惯例,返回的对象应该通过调用 super.clone 获得。

如果没有实现Cloneable 接口,调用clone()方法时会抛出CloneNotSupportedException异常。

a. Class A成员变量类型是java的基本类型时(外加String类型,因为在javaString被写成了一个不可更改的类(immutable class),在所有String类中的函数都不能更改自身的值,每次对String的操作都是生成新的对象,而这些操作如果没有赋值就不存在任何意义)

public class A implements Cloneable {  
    public String name;  
  
    public Object clone() {  
        A o = null;  
        try {  
            o = (A) super.clone();  
        } catch (CloneNotSupportedException e) {  
            e.printStackTrace();  
        }  
        return o;  
    }  
  
}  

 

 

 

b. ClassA成员变量类型是对象时(包括数组(基本类型数组,数组自实现了clone方法),集合(基本类型集合))

 

public class B implements Cloneable {
public String name; 

public Object clone() {  
        B o = null;  
        try {  
            o = (B) super.clone(); //当然Class B也要实现相应clone方法  
        } catch (CloneNotSupportedException e) {  
            e.printStackTrace();  
        }  
        return o;  
    }  
}

public class A implements Cloneable { 
        public String name; 
        public String[] group = new String[2]; 
        public B b;

        public Object clone() { 
              A o = null; 
              try { 
                   o = (A) super.clone(); 
                   o.group = (String[])group.clone(); 
                   o.b = (B)b.clone();
              } catch (CloneNotSupportedException e) { 
                      e.printStackTrace(); 
              } 
              return o; 
        }
}

 

c. Class A存在更为复杂的成员变量时,如非基本类型数组和非基本类型集合时。

 

 

public class B implements Cloneable {
     public String name; 

     public Object clone() {  
         B o = null;  
         try {  
               o = (B) super.clone();  
       } catch (CloneNotSupportedException e) {  
           e.printStackTrace();  
         }  
      return o;  
     }  
}

public class A implements Cloneable {  
    public String name[];  
    public Vector<B> claB;  
      
    public A(){  
        name=new String[2];  
        claB=new Vector<B>();  
    }  
  
    public Object clone() {  
        A o = null;  
        try {  
            o = (A) super.clone();  
            o.name==(String[])name.clone();//深度clone  
            o.claB=new Vector<B>();//将clone进行到底  
            for(int i=0;i<claB.size();i++){  
                B temp=(B)claB.get(i).clone();//当然Class B也要实现相应clone方法  
                o.claB.add(temp);  
            }  
        } catch (CloneNotSupportedException e) {  
            e.printStackTrace();  
        }  
                return o;  
    }  
}  

 

关于数组集合,数组的话就克隆了数组的引用,集合的话就集合容器而已,其中的元素未克隆,说的好像不太清楚,心里懂但是说不清楚真是着急。

总结一下其实克隆每次只克隆对象本身(基本类型),引用类型只克隆引用,不会克隆引用的内容。

 

B. 利用序列化来做深复制,把对象写到流里的过程是序列化(Serilization)过程,而把对象从流中读出来的过程则叫做反序列化(Deserialization)过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。,利用这个特性,可以做深拷贝。

 

public class A implements Cloneable, Serializable {
public String name;

public Object deepCopy() throws IOException {
    Object obj = null;
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(this);
    ByteArrayInputStream bis = new ByteArrayInputStream (bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bis);
    obj = ois.readObject();
    return obj;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值