千家信息网

Java中的clone()和Cloneable接口使用方法是什么

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,本篇内容介绍了"Java中的clone()和Cloneable接口使用方法是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大
千家信息网最后更新 2026年11月04日Java中的clone()和Cloneable接口使用方法是什么

本篇内容介绍了"Java中的clone()和Cloneable接口使用方法是什么"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

clone()和Cloneable接口

clone顾名思义就是克隆,即,复制一个相等的对象,但是不同的引用地址。

我们知道拿到一个对象的地址,只要提供相应的方法就可以修改这个对象,但是如果我们想要得到这个对象去修改它,又想保留这个对象原来的属性,这是就可以使用clone(),它会复制一个内容相同的对象而具有不同内存地址。

Cloneable接口,就是我们要使用clone()必须实现的接口,不然会抛出异常。

public class Bean implements Cloneable {    private String a;     public Bean(String a) {        this.a = a;    }     public String getA() {        return a;    }     @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }     @Override    public boolean equals(Object o) {        if(o instanceof Bean){            Bean bean = (Bean) o;            return bean.getA().equals(a);        }        return false;    }}

在Cloneable 接口中并没有给我们定义任何方法

这里需要重写clone()方法

protected native Object clone() throws CloneNotSupportedException;protected Object clone() throws CloneNotSupportedException {        if (!(this instanceof Cloneable)) {            throw new CloneNotSupportedException("Class " + getClass().getName() +                                                 " doesn't implement Cloneable");        }         return internalClone();    }

它是Object类里面的native方法,它是protected的,根据需要可以写为public,可以看到如果不实现Cloneable接口将会抛出CloneNotSupportedException 异常。

测试一下

try {             Bean a = new Bean("lzy");            Bean b = a;            Bean c = (Bean) a.clone();             Log.i(TAG, "onCreate: " + (a == b));         //true            Log.i(TAG, "onCreate: " + (a.equals(b)));    //true             Log.i(TAG, "onCreate: " + (a == c));         //false            Log.i(TAG, "onCreate: " + (a.equals(c)));    //true          } catch (CloneNotSupportedException e) {            e.printStackTrace();        }

可以看到克隆出来的类的地址是不同的,而内容是相同的。

下面修改一下,在Bean加一个成员变量ChildBean

public class ChildBean implements Cloneable {    private String c;    public String getC() {        return c;    }    public ChildBean(String c) {        this.c = c;    }    @Override    public Object clone() throws CloneNotSupportedException {        return super.clone();    }    @Override    public boolean equals(Object o) {        if (o instanceof ChildBean) {            ChildBean bean = (ChildBean) o;            return bean.getC().equals(c);        }        return false;    }}
public class Bean implements Cloneable {    private String a;    private ChildBean childBean;     public Bean(String a, ChildBean childBean) {        this.a = a;        this.childBean = childBean;    }    public String getA() {        return a;    }     public ChildBean getChildBean() {        return childBean;    }     @Override    public Object clone() throws CloneNotSupportedException {        return super.clone();    }     @Override    public boolean equals(Object o) {        if (o instanceof Bean) {            Bean bean = (Bean) o;            return bean.getA().equals(a);        }        return false;    }}
Bean a = new Bean("lzy", new ChildBean("child"));            Bean b = a;            Bean c = (Bean) a.clone();             Log.i(TAG, "onCreate: " + (a.getChildBean() == b.getChildBean()));         //true            Log.i(TAG, "onCreate: " + (a.getChildBean().equals(b.getChildBean())));    //true             Log.i(TAG, "onCreate: " + (a.getChildBean() == c.getChildBean()));         //true            Log.i(TAG, "onCreate: " + (a.getChildBean().equals(c.getChildBean())));    //true

测试发现有一个结果不是我们所预期的,这意味着并没有真正克隆ChildBean,只是克隆的它的内存地址,导致两个具有相同的内存地址,这也就是浅克隆,此时我们需要的是深克隆,需要按照下面方法修改,重写clone()方法

  @Override    public Object clone() throws CloneNotSupportedException {        Bean bean = (Bean) super.clone();        bean.childBean = (ChildBean) bean.childBean.clone();        return bean;    }

但是这样做如果有很多层的类,那每一层都需要去重写,显得很麻烦。所以我们可以用下面的工具类来实现

public class BeanUtil {    public static  T cloneTo(T src) throws RuntimeException {        ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();        ObjectOutputStream out = null;        ObjectInputStream in = null;        T dist = null;        try {            out = new ObjectOutputStream(memoryBuffer);            out.writeObject(src);            out.flush();            in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));            dist = (T) in.readObject();        } catch (Exception e) {            throw new RuntimeException(e);        } finally {            if (out != null)                try {                    out.close();                    out = null;                } catch (IOException e) {                    throw new RuntimeException(e);                }            if (in != null)                try {                    in.close();                    in = null;                } catch (IOException e) {                    throw new RuntimeException(e);                }        }        return dist;    }}
Bean a = new Bean("lzy", new ChildBean("child"));        Bean b = BeanUtil.cloneTo(a);         Log.i(TAG, "onCreate: " + (a.getChildBean() == b.getChildBean()));         //false        Log.i(TAG, "onCreate: " + (a.getChildBean().equals(b.getChildBean())));    //true

这样就可以很轻松的得到我们预期的结果,但是记得每一个类都要去 实现Serializable接口。

Cloneable和clone()的总结

1.Cloneable 的用途

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

2.克隆的分类

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

(2)深克隆(deep clone),深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

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

3.克隆的举例

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

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      }  }

4.浅克隆的举例

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      }  }

5.深克隆的举例

如果要深克隆,需要重写(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()方法。

"Java中的clone()和Cloneable接口使用方法是什么"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

对象 方法 拷贝 接口 地址 自动生成 生成 内容 中包 不同 相同 内存 就是 属性 使用方法 两个 变量 指向 更多 知识 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络科技有限互联网 广州互联网科技公司 奇酷互联网络科技公司 上游互联网科技 苏州大垚互联网科技 剑昆互联网络科技有限公司临桂 世界互联网科技公司市值排名 岳阳华臻互联网科技有限公司 和信科技工业互联网 移动互联网年度科技创新 新兴科技互联网创新大赛颁奖典礼 互联网科技和法律行业 工业互联网展湾科技股份有限公司 伍佰万互联网科技怎么赚钱 城市宝互联网科技有限公司 广东鹅鹅鹅互联网科技有限公司 科技互联网行业投资研究 银川新华互联网科技学校原画 北京军民互联网科技公司 承德科技产业互联网平台 互联网科技工作委员会主任 中国互联网科技工作委员会毛军 上游互联网科技 互联网科技宣传片 科技类的互联网平台 富国互联网科技创新基金 燊美集互联网科技有限公司 科技大学互联网 徐州市互联网科技有限公司 富国互联网科技002692
0