首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >克隆()与复制构造函数与工厂方法?

克隆()与复制构造函数与工厂方法?
EN

Stack Overflow用户
提问于 2009-07-09 19:52:56
回答 9查看 58.5K关注 0票数 86

我在Java中快速实现了克隆(),并找到了:http://www.javapractices.com/topic/TopicAction.do?Id=71

它有以下评论:

复制构造函数和静态工厂方法提供了一种替代克隆的方法,并且更容易实现。

我只想做一份很深的拷贝。实现克隆()似乎很有意义,但这篇谷歌排名很高的文章让我有点害怕。

下面是我注意到的问题:

复制构造函数不适用于泛型。

以下是一些不编译的伪代码。

代码语言:javascript
运行
复制
public class MyClass<T>{
   ..
   public void copyData(T data){
       T copy=new T(data);//This isn't going to work.    
   }
   ..
}

示例1:在泛型类中使用复制构造函数。

工厂方法没有标准名称。

有一个可重用代码的接口是很好的。

代码语言:javascript
运行
复制
public class MyClass<T>{
    ..
    public void copyData(T data){
        T copy=data.clone();//Throws an exception if the input was not cloneable
    }
    ..
}

示例2:在泛型类中使用克隆()。

我注意到克隆不是一种静态的方法,但是是否仍有必要对所有受保护的字段进行深度复制?在实现克隆()时,在非克隆子类中抛出异常的额外工作对我来说似乎微不足道。

我是不是遗漏了什么?任何见解都将不胜感激。

EN

回答 9

Stack Overflow用户

发布于 2009-07-09 20:02:45

还有Builder模式。有关详细信息,请参阅有效Java。

我不明白你的评价。在副本构造函数中,您完全了解类型,为什么需要使用泛型?

代码语言:javascript
运行
复制
public class C {
   public int value;
   public C() { }
   public C(C other) {
     value = other.value;
   }
}

最近也有一个类似的问题,这里

代码语言:javascript
运行
复制
public class G<T> {
   public T value;
   public G() { }
   public G(G<? extends T> other) {
     value = other.value;
   }
}

可运行的样本:

代码语言:javascript
运行
复制
public class GenTest {
    public interface Copyable<T> {
        T copy();
    }
    public static <T extends Copyable<T>> T copy(T object) {
        return object.copy();
    }
    public static class G<T> implements Copyable<G<T>> {
        public T value;
        public G() {
        }
        public G(G<? extends T> other) {
            value = other.value;
        }
        @Override
        public G<T> copy() {
            return new G<T>(this);
        }
    }
    public static void main(String[] args) {
        G<Integer> g = new G<Integer>();
        g.value = 1;
        G<Integer> f = g.copy();
        g.value = 2;
        G<Integer> h = copy(g);
        g.value = 3;
        System.out.printf("f: %s%n", f.value);
        System.out.printf("g: %s%n", g.value);
        System.out.printf("h: %s%n", h.value);
    }
}
票数 25
EN

Stack Overflow用户

发布于 2009-07-09 19:59:53

Java没有与C++相同的复制构造函数。

您可以有一个构造函数,它将同一类型的对象作为参数,但是很少有类支持这一点。(少于支持克隆的数目)

对于一般的克隆,我有一个助手方法,它创建一个类的新实例,并使用反射(实际上类似反射,但速度更快)从原始的(浅拷贝)复制字段。

对于深拷贝,一种简单的方法是序列化对象并反序列化它.

顺便说一句:我的建议是使用不可变的对象,这样就不需要克隆它们了。;)

票数 11
EN

Stack Overflow用户

发布于 2017-01-11 18:09:47

以下是许多开发人员不使用Object.clone()的一些缺点

  1. 使用Object.clone()方法需要在代码中添加大量语法,如实现Cloneable接口、定义clone()方法和处理CloneNotSupportedException,最后调用Object.clone()并将其转换为我们的对象。
  2. Cloneable接口缺乏clone()方法,它是一个标记接口,其中没有任何方法,我们仍然需要实现它,只是告诉JVM我们可以在对象上执行clone()
  3. Object.clone()是受保护的,所以我们必须提供自己的clone(),并从它间接调用Object.clone()
  4. 我们对对象构造没有任何控制,因为Object.clone()不调用任何构造函数。
  5. 如果我们在子类中编写clone()方法,例如Person,那么它的所有超类都应该在它们中定义clone()方法,或者从另一个父类继承它,否则super.clone()链将失败。
  6. Object.clone()只支持浅拷贝,因此新克隆的对象的引用字段仍然保留原始对象的字段。为了克服这一问题,我们需要在我们类持有的每个引用类中实现clone(),然后在clone()方法中分别克隆它们,如下例所示。
  7. 我们不能在Object.clone()中操作最终字段,因为最终字段只能通过构造函数进行更改。在我们的例子中,如果我们希望每个Person对象都是惟一的id,如果我们使用Object.clone(),我们将得到重复的对象,因为Object.clone()不会调用构造函数,并且最终的id字段不能从Person.clone()中修改。

复制构造函数比Object.clone()更好,因为它们

  1. 不要强迫我们实现任何接口或抛出任何异常,但如果需要,我们肯定可以这样做。
  2. 不需要任何施放。
  3. 不需要我们依赖未知的对象创建机制。
  4. 不要要求父类遵循任何契约或实现任何东西。
  5. 允许我们修改最后的字段。
  6. 允许我们完全控制对象的创建,我们可以在其中编写初始化逻辑。

阅读有关Java克隆-复制构造器与克隆的更多信息

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

https://stackoverflow.com/questions/1106102

复制
相关文章

相似问题

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