前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java--对象的克隆

Java--对象的克隆

作者头像
SuperHeroes
发布2018-05-22 16:08:49
7140
发布2018-05-22 16:08:49
举报
文章被收录于专栏:云霄雨霁云霄雨霁

因为Java方法中对象参数的传递是句柄(引用)传递,所以方法中对句柄的改动会影响到原对象。

很少调用一个方法来处理它的参数,在实际编程中也要避免改变参数的情况。但如果我们需要在一个方法的调用期间修改一个参数,且不打算修改外部实体,就应该在自己方法的内部制作一个那个参数的副本来保护那个参数。

制作对象副本需要使用clone()方法。这个方法在基础类Object 中定义成“protected”模式。所以在希望克隆的任何衍生类中,必须将其覆盖为“public”模式。例如,标准库类Vector 覆盖了 clone(),所以能为 Vector调用clone()。

class Int {
    private int i;
    public Int(int ii) { i = ii; }
    public void increment() { i++; }
    public String toString() {
        return Integer.toString(i);
    }
}
public class Cloning {
    public static void main(String[] args) {
        Vector v = new Vector();    //创建Vector
        for(int i = 0; i < 10; i++ )
            v.addElement(new Int(i));    //添加对象
        System.out.println("v: " + v);    //第一次输出  
        Vector v2 = (Vector)v.clone();    //创建Vector的复制
        for(Enumeration e = v2.elements();   
            e.hasMoreElements(); )    //对复制的Vector中的对象进行+1操作
        ((Int)e.nextElement()).increment();
        System.out.println("v: " + v);     //第二次输出
    }
} 

上面代码涉及到“深拷贝“和”浅拷贝“的问题。这个例子中由于别名问题,原Vector和拷贝的Vector都包含了相同的对象,即两个Vector是完全独立的,但其中容纳的东西相同,这就是”浅拷贝“。”浅拷贝“只拷贝本对象,该对象内部指向的其他对象,以及”其他对象“又指向的另外的对象都不拷贝。

若要“深拷贝”,必须在覆盖的clone()里采取附加的操作。 通常在调用 super.clone()后,为对象内每个句柄都明确调用一个 clone();否则那些句柄会别名变成原始对象的句柄。当然,必须保证对象内的每个句柄自身也都实现了“深拷贝”。

使类具有克隆能力:

因为Object类将clone()定义为”protected", 所以衍生类不做点什么的话,是无法具有克隆能力的(很简单,对象无法调用本类的protected方法)。

1、覆盖clone()方法为public. 

想要类可以克隆,记住两点:

  1. 几乎肯定要调用super.clone();
  2. 将clone()设置为public。

注意:因为Java不可能在衍生之后反而缩小方法的访问范围,所以一旦对象变得可以克隆,从它衍生的任何东西都是可以克隆的。(下面会有一种特殊机制关闭克隆能力)

2、实现Cloneable接口

Cloneable接口是空的,我们不需要为它实现任何方法。它的存在有两个原因:

  • 可能有一个上溯造型句柄指向一个基础类型,而且不知道它是否真的能克隆那个对象。在这种情况下,可用instanceof 关键字调查句柄是否确实同一个能克隆的对象连接。
  • 考虑到我们可能不愿所有对象类型都能克隆。所以Object.clone()会验证一个类是否真的是实现了Cloneable 接口。若答案是否定的,则“掷”出一个 CloneNotSupportedException违例。

所以在一般情况下,我们必须将“implement Cloneable”作为对克隆能力提供支持的一部分。

经过上面两步,就可以创建自己的可克隆的类:

class MyObject implements Cloneable {
    int i;
    MyObject(int ii) { i = ii; }
    public Object clone() {
        Object o = null;
        try {
            o = super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("MyObject can't clone");
        }
        return o;
    }
    public String toString() { return Integer.toString(i); }
}

 消除克隆能力:

  1. 不实现 Cloneable 来试着防止克隆,并覆盖clone(),以产生一个违例。这样,从它衍生出来的类的clone()方法调用super.clone()时会抛出异常。
  2. 将类设为final,从而防止克隆。若clone()尚未被我们的任何一个上级类覆盖,这一设想便不会成功。 若已被覆盖,那么再一次覆盖它,并“掷”出一个 CloneNotSupportedException(克隆不支持)违例。为担保克隆被禁止,将类设为final是唯一的办法。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档