您当前的位置:首页 > 计算机 > 编程开发 > Java

1.32. 哪个类包含 clone 方法?是 Cloneable 还是 Object?

时间:12-14来源:作者:点击数:

java.lang.Cloneable 是一个标示性接口,不包含任何方法,clone 方法在 object 类中定义。并且需要知道 clone() 方法是一个本地方法,这意味着它是由 c 或 c++ 或 其他本地语言实现的。


Cloneable 的用途

Cloneable 和 Serializable 一样都是标记型接口,它们内部都没有方法和属性,implements Cloneable 表示该对象能被克隆,能使用 Object.clone() 方法。如果没有 implements Cloneable 的类调用 Object.clone() 方法就会抛出 CloneNotSupportedException。

克隆的分类

  • 浅克隆(shallow clone),浅拷贝是指拷贝对象时仅仅拷贝对象本身和对象中的基本变量,而不拷贝对象包含的引用指向的对象。
  • 深克隆(deep clone),深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

举例区别一下:对象A1中包含对B1的引用,B1中包含对C1的引用。浅拷贝A1得到A2,A2中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归,深拷贝A1得到 A2,A2 中包含对B2(B1的copy)的引用,B2中包含对C2(C1 的 copy)的引用。

克隆的举例

要让一个对象进行克隆,其实就是两个步骤:

  1. 让该类实现 java.lang.Cloneable 接口;
  2. 重写(override)Object 类的 clone() 方法。
public class Wife implements Cloneable {  
  private int id;  
  private String name;  

  public int getId() {  
    return id;  
  }  

  public void setId(int id) {  
    this.id = id;  
  }  

  public String getName() {  
    return name;  
  }  

  public void setName(String name) {  
    this.name = name;  
  }  

  public Wife(int id,String name) {  
    this.id = id;  
    this.name = name;  
  }  

  @Override  
  public int hashCode() {//myeclipse自动生成的  
    final int prime = 31;  
    int result = 1;  
    result = prime * result + id;  
    result = prime * result + ((name == null) ? 0 : name.hashCode());  
    return result;  
  }  

  @Override  
  public boolean equals(Object obj) {//myeclipse自动生成的  
    if (this == obj)  
      return true;  
    if (obj == null)  
      return false;  
    if (getClass() != obj.getClass())  
      return false;  
    Wife other = (Wife) obj;  
    if (id != other.id)  
      return false;  
    if (name == null) {  
      if (other.name != null)  
        return false;  
    } else if (!name.equals(other.name))  
      return false;  
    return true;  
  }  

  @Override  
  public Object clone() throws CloneNotSupportedException {  
    return super.clone();  
  }  

  /** 
   * @param args 
   * @throws CloneNotSupportedException  
   */  
  public static void main(String[] args) throws CloneNotSupportedException {  
    Wife wife = new Wife(1,"wang");  
    Wife wife2 = null;  
    wife2 = (Wife) wife.clone();  
    System.out.println("class same="+(wife.getClass()==wife2.getClass()));//true  
    System.out.println("object same="+(wife==wife2));//false  
    System.out.println("object equals="+(wife.equals(wife2)));//true  
  }  
}  

浅克隆的举例

public class Husband implements Cloneable {  
  private int id;  
  private Wife wife;  

  public Wife getWife() {  
    return wife;  
  }  

  public void setWife(Wife wife) {  
    this.wife = wife;  
  }  

  public int getId() {  
    return id;  
  }  

  public void setId(int id) {  
    this.id = id;  
  }  

  public Husband(int id) {  
    this.id = id;  
  }  

  @Override  
  public int hashCode() {//myeclipse自动生成的  
    final int prime = 31;  
    int result = 1;  
    result = prime * result + id;  
    return result;  
  }  

  @Override  
  protected Object clone() throws CloneNotSupportedException {  
    return super.clone();  
  }  

  @Override  
  public boolean equals(Object obj) {//myeclipse自动生成的  
    if (this == obj)  
      return true;  
    if (obj == null)  
      return false;  
    if (getClass() != obj.getClass())  
      return false;  
    Husband other = (Husband) obj;  
    if (id != other.id)  
      return false;  
    return true;  
  }  

  /** 
   * @param args 
   * @throws CloneNotSupportedException  
   */  
  public static void main(String[] args) throws CloneNotSupportedException {  
    Wife wife = new Wife(1,"jin");  
    Husband husband = new Husband(1);  
    Husband husband2 = null;  
    husband.setWife(wife);  
    husband2 = (Husband) husband.clone();  
    System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true  
    System.out.println("husband object same="+(husband==husband2));//false  
    System.out.println("husband object equals="+(husband.equals(husband)));//true  
    System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true  
    System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//true  
    System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true  
  }  
}  

深克隆的举例

如果要深克隆,需要重写(override)Object 类的 clone() 方法,并且在方法内部调用持有对象的 clone() 方法;注意如下代码的 clone() 方法

public class Husband implements Cloneable {  
  private int id;  
  private Wife wife;  

  public Wife getWife() {  
    return wife;  
  }  

  public void setWife(Wife wife) {  
    this.wife = wife;  
  }  

  public int getId() {  
    return id;  
  }  

  public void setId(int id) {  
    this.id = id;  
  }  

  public Husband(int id) {  
    this.id = id;  
  }  

  @Override  
  public int hashCode() {//myeclipse自动生成的  
    final int prime = 31;  
    int result = 1;  
    result = prime * result + id;  
    return result;  
  }  

  @Override  
  protected Object clone() throws CloneNotSupportedException {  
    Husband husband = (Husband) super.clone();  
    husband.wife = (Wife) husband.getWife().clone();  
    return husband;  
  }  

  @Override  
  public boolean equals(Object obj) {//myeclipse自动生成的  
    if (this == obj)  
      return true;  
    if (obj == null)  
      return false;  
    if (getClass() != obj.getClass())  
      return false;  
    Husband other = (Husband) obj;  
    if (id != other.id)  
      return false;  
    return true;  
  }  

  /** 
   * @param args 
   * @throws CloneNotSupportedException  
   */  
  public static void main(String[] args) throws CloneNotSupportedException {  
    Wife wife = new Wife(1,"jin");  
    Husband husband = new Husband(1);  
    Husband husband2 = null;  
    husband.setWife(wife);  
    husband2 = (Husband) husband.clone();  
    System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true  
    System.out.println("husband object same="+(husband==husband2));//false  
    System.out.println("husband object equals="+(husband.equals(husband)));//true  
    System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true  
    System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//false  
    System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true  
  }  
}  

但是也有不足之处,如果 Husband 内有N个对象属性,突然改变了类的结构,还要重新修改 clone() 方法。解决办法:可以使用 Serializable 运用反序列化手段,调用 java.io.ObjectInputStream 对象的 readObject() 方法。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐