java 用泛型克隆

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/803971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:52:50  来源:igfitidea点击:

Cloning with generics

javaclone

提问by Etam

Once upon a time there was a class:

从前有一堂课:

public class Scope<C extends Cloneable & Comparable<C>> implements Comparable<Scope<C>>, Cloneable, Serializable {

   private C starts;
   private C ends;
   ...

   @SuppressWarnings("unchecked")
   @Override
   public Object clone() {
       Scope<C> scope;
       try {
           scope = (Scope<C>) super.clone();
           scope.setStarts((C) starts.clone()); // The method clone() from the type Object is not visible
           scope.setEnds((C) ends.clone()); // The method clone() from the type Object is not visible
       } catch (CloneNotSupportedException e) {
           throw new RuntimeException("Clone not supported");
       }
       return scope;
   }
}

In Object we have:

在对象中,我们有:

protected native Object clone() throws CloneNotSupportedException;

And Cloneable interface is:

和 Cloneable 接口是:

public interface Cloneable { 
}

How should I clone this?

我应该如何克隆这个?

采纳答案by Cojones

I think the current green answer is bad, why you might ask?

我认为目前的绿色答案很糟糕,你为什么要问?

  • It adds a lot of code
  • It requires you to list all fields to be copied and do this
  • This will not work for Lists when using clone() (This is what clone() for HashMap says: Returns a shallow copy of this HashMap instance: the keys and valuesthemselves are not cloned.) so you end up doing it manually (this makes me cry)
  • 它添加了很多代码
  • 它要求您列出要复制的所有字段并执行此操作
  • 当使用 clone() 时,这对 Lists 不起作用(这就是 HashMap 的 clone() 所说的:返回此 HashMap 实例的浅拷贝:键和值本身没有被克隆。)所以你最终手动完成(这使得我哭了)

Oh and by the way serialization is also bad, you might have to add Serializable all over the place (this also makes me cry).

哦,顺便说一句,序列化也很糟糕,你可能不得不到处添加 Serializable (这也让我哭了)。

So what is the solution:

那么解决方法是什么:

Java Deep-Cloning library The cloning libraryis a small, open source (apache licence) java library which deep-clones objects. The objects don't have to implement the Cloneable interface. Effectivelly, this library can clone ANY java objects. It can be used i.e. in cache implementations if you don't want the cached object to be modified or whenever you want to create a deep copy of objects.

Java 深度克隆库 克隆库是一个小型的开源(Apache 许可)java 库,它可以深度克隆对象。这些对象不必实现 Cloneable 接口。实际上,这个库可以克隆任何 java 对象。如果您不希望缓存对象被修改,或者您想创建对象的深层副本,则可以在缓存实现中使用它。

Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);

Check it out at http://code.google.com/p/cloning/

http://code.google.com/p/cloning/查看

回答by Michael Myers

This is one reason why no one likes Cloneable. It's supposed to be a marker interface, but it's basically useless because you can't clone an arbitrary Cloneableobject without reflection.

这也是没人喜欢的Cloneable原因之一。它应该是一个标记接口,但它基本上没有用,因为你不能在Cloneable没有反射的情况下克隆任意对象。

Pretty much the only way to do this is to create your own interface with a publicclone()method (it doesn't have to be called "clone()"). Here's an examplefrom another StackOverflow question.

几乎唯一的方法是使用公共clone()方法创建您自己的接口(它不必被称为“ clone()”)。这是另一个 StackOverflow 问题的示例

回答by Istvan

Hopefully I've resolved the problem of generic cloningin Java:

希望我已经解决了Java中通用克隆的问题:

public class Generic<T> {
  private T data;

  public Generic() {
    // ...
  }

  @SuppressWarnings("unchecked")
  @Override
  public Object clone() {
    Generic<T> cloned = new Generic<T>();
    try {
      cloned.data = (T) data.getClass().getMethod("clone").invoke(data);
    } catch (Exception e) {
      // ...
    }
    return cloned;
  }
}

回答by Yishai

Slightly OT, but you could save yourself a lot of future grief with this:

有点过时了,但是您可以通过以下方式为自己节省很多未来的悲伤:

   catch (CloneNotSupportedException e) {
       throw new RuntimeException("Clone not supported", e);
   }

So that when you get a stack trace you know which object caused the problem.

这样当您获得堆栈跟踪时,您就知道是哪个对象导致了问题。

To answer the core question, your own interface that implements a publicclone() as mmyers wrote and require that C extend that as well.

为了回答核心问题,您自己的接口实现了mmyers 编写的公共clone() 并要求 C 也扩展它。

回答by Julien Chastang

As a general comment, avoid using Object.clone() whenever possible. If you have control over the code in question, implement a copy constructor instead. See herefor information.

作为一般性评论,请尽可能避免使用 Object.clone()。如果您可以控制相关代码,请改为实现复制构造函数。有关信息,请参见此处

回答by Eddie

As you see, if a class tries to implement Cloneableand you want a deepclone, then all of your constituent objects needs to be immutable, primitive, or need to also be Cloneable.

如您所见,如果一个类试图实现Cloneable并且您想要一个深度克隆,那么您的所有组成对象都需要是不可变的、原始的,或者也需要是可克隆的。

Often, a better and easier approach is to create a copy constructor.

通常,更好、更简单的方法是创建复制构造函数。

public class Scope<C extends Comparable<C>> implements Comparable<Scope<C>>, Serializable {
    private C starts;
    private C ends;
    public Scope(final Scope original) {
       starts = new C(original.starts);
       ends = new C(original.ends);
       // initialize all my other fields from "original"
    }
}

and of course you need a copy constructor on Cthat is capable of handling polymorphism.

当然,您需要一个C能够处理多态的复制构造函数。

If you have no access or ability to modify the source to C, then any method of copying, no matter what the method, will be very difficult and potentially impossible. For example, it is not possible to make a copy of an enuminstance.

如果您无法访问或无法将源修改为C,那么任何复制方法,无论采用何种方法,都将非常困难,并且可能是不可能的。例如,不可能制作enum实例的副本。