首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Cloneable如何在Java中工作,以及如何使用它?

Cloneable如何在Java中工作,以及如何使用它?
EN

Stack Overflow用户
提问于 2010-11-02 20:35:49
回答 5查看 81.2K关注 0票数 107

我想知道以下几点:

  1. Cloneable意味着通过实现Cloneable接口,我们可以拥有对象的克隆或副本。这样做有什么好处和缺点?
  2. ,如果对象是一个复合对象,如何进行递归克隆?
EN

回答 5

Stack Overflow用户

发布于 2010-11-02 20:50:55

令人遗憾的是,Cloneable本身只是一个标记-接口,也就是说:它不定义克隆()方法。

所做的是更改受保护的Object.clone()方法的行为,该方法将为不实现Cloneable的类抛出一个CloneNotSupportedException,并对这样做的类执行一个按成员划分的浅拷贝。

即使这是您要寻找的行为,您仍然需要实现自己的克隆()方法,以便将其公之于众。

在实现您自己的克隆()时,我们的想法是从super.clone()创建的对象开始,该对象保证属于正确的类,然后执行任何额外的字段填充,以防浅层副本不是您想要的。从克隆()调用构造函数是有问题的,因为如果子类想要添加自己的额外可复制逻辑,则会破坏继承;如果要调用super.clone(),则在本例中将得到错误类的对象。

但是,这种方法绕过了在构造函数中定义的任何逻辑,这可能会产生问题。

另一个问题是,任何忘记覆盖克隆()的子类都将自动继承默认的浅拷贝,在发生可变状态(现在将在源和副本之间共享)时,这可能不是您想要的。

由于这些原因,大多数开发人员不会使用Cloneable,而只是实现一个复制构造函数。

欲了解更多信息和克隆的潜在缺陷,我强烈推荐由约书亚·布洛赫撰写的“有效Java”一书

票数 42
EN

Stack Overflow用户

发布于 2010-11-02 20:45:26

  1. 克隆调用了一种非语言的方法来构造对象--没有构造函数。
  2. 克隆要求您以某种方式处理CloneNotSupportedException,或者麻烦客户端代码来处理它。
  3. 的好处很小,您只需要手动编写复制构造函数。

所以,明智地使用克隆。它并没有给你足够的好处,相比你需要努力去做好每件事。

票数 13
EN

Stack Overflow用户

发布于 2014-02-15 22:13:48

克隆是一种基本的编程模式。事实上,Java在许多方面可能没有很好地实现它,这一点丝毫没有减少克隆的必要性。而且,实现克隆是很容易的,不管你希望它如何工作,浅层,深,混合,什么都行。您甚至可以为函数使用名称克隆,如果您愿意,也不能实现Cloneable。

假设我有A、B和C类,其中B和C是从A派生的,如果我有一个A类型的对象列表,如下所示:

代码语言:javascript
复制
ArrayList<A> list1;

现在,这个列表可以包含A、B或C类型的对象,您不知道这些对象是什么类型。所以,你不能像这样复制列表:

代码语言:javascript
复制
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(new A(a));
}

如果对象实际上是B或C类型的,则不会得到正确的副本。如果A是抽象的呢?现在,有人建议这样做:

代码语言:javascript
复制
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    if(a instanceof A) {
        list2.add(new A(a));
    } else if(a instanceof B) {
        list2.add(new B(a));
    } else if(a instanceof C) {
        list2.add(new C(a));
    }
}

这是个非常非常糟糕的主意。如果您添加了一个新的派生类型怎么办?如果B或C在另一个包中,而您在这个类中没有访问它们的权限,该怎么办?

你想做的是:

代码语言:javascript
复制
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(a.clone());
}

许多人已经指出了为什么克隆的基本Java实现是有问题的。但是,它很容易克服这种方式:

在A班:

代码语言:javascript
复制
public A clone() {
    return new A(this);
}

在B班:

代码语言:javascript
复制
@Override
public B clone() {
    return new B(this);
}

在C班:

代码语言:javascript
复制
@Override
public C clone() {
    return new C(this):
}

我没有实现Cloneable,只是使用相同的函数名。如果你不喜欢,就说点别的吧。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4081858

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档