关于 Java 可克隆
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4081858/
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
About Java cloneable
提问by daydreamer
I was looking for some tutorials explaining about Java Cloneable
, but did not get any good links, and Stack Overflow is becoming more obvious choice anyways.
我一直在寻找一些解释 Java 的教程Cloneable
,但没有得到任何好的链接,无论如何,堆栈溢出正变得越来越明显。
I would like to know the following:
我想知道以下内容:
Cloneable
means we can have a clone or a copy of objects, by implementing theCloneable
interface. What are the advantages and disadvantages of doing that?- How does the recursive cloning happen if the object is a composite object?
Cloneable
意味着我们可以通过实现Cloneable
接口来克隆或复制对象。这样做有什么好处和坏处?- 如果对象是复合对象,递归克隆如何发生?
采纳答案by Bozho
The first thing you should know about Cloneable
is - don't use it.
你应该知道的第一件事Cloneable
是 - 不要使用它。
It is very hard to implement cloning with Cloneable
right, and the effort is not worth it.
Cloneable
正确地实施克隆是非常困难的,而且付出的努力是不值得的。
Instead of that use some other options, like apache-commons SerializationUtils
(deep-clone) or BeanUtils
(shallow-clone), or simply use a copy-constructor.
而不是使用其他一些选项,如 apache-commons SerializationUtils
(deep-clone) 或BeanUtils
(shallow-clone),或者简单地使用复制构造函数。
See herefor the views of Josh Bloch about cloning with Cloneable
, which explains the many drawbacks of the approach. (Joshua Blochwas a Sun employee, and led the development of numerous Java features.)
请参阅此处了解 Josh Bloch 关于使用 克隆的观点Cloneable
,这解释了该方法的许多缺点。(Joshua Bloch是 Sun 的员工,领导了许多 Java 功能的开发。)
回答by Vladimir Ivanov
- Cloning invokes an extra-linguistic way of constructing objects - without constructors.
- Cloning requires you to treat somehow with CloneNotSupportedException - or to bother client code for treating it.
- Benefits are small - you just don't have to manually write a copying constructor.
- 克隆调用了一种构建对象的超语言方式 - 没有构造函数。
- 克隆要求您以某种方式处理 CloneNotSupportedException - 或者打扰客户端代码来处理它。
- 好处很小 - 您只是不必手动编写复制构造函数。
So, use Cloneable judiciously. It doesn't give you sufficient benefits in comparison with the effort you need to apply to do everything right.
因此,请明智地使用 Cloneable。与您为做好每件事所需的努力相比,它并没有给您带来足够的好处。
回答by ILMTitan
A) There are not a whole lot of advantages of clone over a copy constructor. Probably the biggest one is the ability to create a new object of the exact same dynamic type (assuming the declared type is clonable and has a public clone method).
A) 与复制构造函数相比,克隆并没有很多优势。可能最大的一个是能够创建一个完全相同的动态类型的新对象(假设声明的类型是可克隆的并且有一个公共的克隆方法)。
B) The default clone creates a shallow copy, and it will remain a shallow copy unless your clone implementation changes that. This can be difficult, especially if your class has final fields
B) 默认克隆创建一个浅拷贝,除非你的克隆实现改变它,否则它将保持浅拷贝。这可能很困难,特别是如果您的课程有 final 字段
Bozho is right, clone can be difficult to get right. A copy constructor/factory will serve most needs.
Bozho 是对的,克隆很难做到。复制构造函数/工厂将满足大多数需求。
回答by Luke Hutteman
Cloneable itself is unfortunately just a marker-interface, that is: it does not define the clone() method.
不幸的是,Cloneable 本身只是一个标记接口,也就是说:它没有定义 clone() 方法。
What is does, is change the behavior of the protected Object.clone() method, which will throw a CloneNotSupportedException for classes that do not implement Cloneable, and perform a member-wise shallow copy for classes that do.
它的作用是改变受保护的 Object.clone() 方法的行为,该方法将为未实现 Cloneable 的类抛出 CloneNotSupportedException,并为实现 Cloneable 的类执行成员方式的浅拷贝。
Even if this is the behavior you are looking for, you'll still need to implement your own clone() method in order to make it public.
即使这是您正在寻找的行为,您仍然需要实现自己的 clone() 方法以使其公开。
When implementing your own clone(), the idea is to start with the object create by super.clone(), which is guaranteed to be of the correct class, and then do any additional population of fields in case a shallow copy is not what you want. Calling a constructor from clone() would be problematic as this would break inheritance in case a subclass wants to add its own additional cloneable logic; if it were to call super.clone() it would get an object of the wrong class in this case.
在实现你自己的 clone() 时,想法是从 super.clone() 创建的对象开始,它保证是正确的类,然后做任何额外的字段填充,以防浅拷贝不是什么你要。从 clone() 调用构造函数会出现问题,因为如果子类想要添加自己的附加可克隆逻辑,这会破坏继承;如果它要调用 super.clone() 在这种情况下它会得到一个错误类的对象。
This approach bypasses any logic that may be defined in your constructors though, which could potentially be problematic.
但是,这种方法绕过了可能在您的构造函数中定义的任何逻辑,这可能会出现问题。
Another problem is that any subclasses that forget to override clone() will automatically inherit the default shallow copy, which is likely not what you want in case of mutable state (which will now be shared between the source and the copy).
另一个问题是任何忘记覆盖 clone() 的子类将自动继承默认的浅拷贝,这在可变状态(现在将在源和副本之间共享)的情况下可能不是您想要的。
Most developers don't use Cloneable for these reasons, and simply implement a copy constructor instead.
由于这些原因,大多数开发人员不使用 Cloneable,而是简单地实现一个复制构造函数。
For more information and potential pitfalls of Cloneable, I highly recommend the book Effective Java by Joshua Bloch
有关 Cloneable 的更多信息和潜在陷阱,我强烈推荐 Joshua Bloch 的 Effective Java 一书
回答by Charles
Cloning is a basic programming paradigm. The fact that Java may have implemented it poorly in many ways does not at all diminish the need for cloning. And, it is easy to implement cloning that will work however you want it to work, shallow, deep, mixed, whatever. You can even use the name clone for the function and not implement Cloneable if you like.
克隆是一种基本的编程范式。Java 在许多方面可能没有很好地实现它这一事实并没有减少对克隆的需求。而且,很容易实现克隆,无论你希望它如何工作,浅的、深的、混合的,等等。如果您愿意,您甚至可以为该函数使用名称 clone,而不实现 Cloneable。
Suppose I have classes A, B, and C, where B and C are derived from A. If I have a list of objects of type A like this:
假设我有类 A、B 和 C,其中 B 和 C 是从 A 派生的。如果我有一个 A 类型的对象列表,如下所示:
ArrayList<A> list1;
Now, that list can contains objects of type A, B, or C. You don't know what type the objects are. So, you can't copy the list like this:
现在,该列表可以包含 A、B 或 C 类型的对象。您不知道这些对象是什么类型。所以,你不能像这样复制列表:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(new A(a));
}
If the object is actually of type B or C, you will not get the right copy. And, what if A is abstract? Now, some people have suggested this:
如果对象实际上是 B 或 C 类型,您将无法获得正确的副本。而且,如果 A 是抽象的呢?现在,有些人提出了这个建议:
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));
}
}
This is a very, very bad idea. What if you add a new derived type? What if B or C are in another package and you don't have access to them in this class?
这是一个非常非常糟糕的主意。如果添加新的派生类型会怎样?如果 B 或 C 位于另一个包中而您无法在该类中访问它们怎么办?
What you would like to do is this:
你想要做的是:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(a.clone());
}
Lots of people have indicated why the basic Java implementation of clone is problematic. But, it's easily overcome this way:
很多人已经指出了为什么 clone 的基本 Java 实现是有问题的。但是,它很容易通过这种方式克服:
In class A:
在 A 类中:
public A clone() {
return new A(this);
}
In class B:
B类:
@Override
public B clone() {
return new B(this);
}
In class C:
在 C 类中:
@Override
public C clone() {
return new C(this):
}
I'm not implementing Cloneable, just using the same function name. If you don't like that, name it something else.
我没有实现 Cloneable,只是使用相同的函数名称。如果您不喜欢那样,请命名为其他名称。
回答by 027
What are disadvantages of Cloneable?
Cloneable 的缺点是什么?
Cloning is very dangerous if the object whom you are copying has composition.You need to think about below possible side effect in this case because clone creates shallow copy:
如果您要复制的对象具有组合,则克隆非常危险。 在这种情况下,您需要考虑以下可能的副作用,因为克隆会创建浅拷贝:
Let say you have one object to handle db related manipulation. Say, that object has Connection
object as one of the property.
假设您有一个对象来处理与数据库相关的操作。说,那个对象有Connection
对象作为属性之一。
So when someone creates clone of originalObject
, The object being created, let say, cloneObject
.
Here the originalObject
and cloneObject
hold the same reference for Connection
object.
因此,当有人创建 的克隆时originalObject
,正在创建的对象,比如说,cloneObject
。这里originalObject
和cloneObject
持有相同的Connection
对象引用。
Let say originalObject
closes the Connection
object, so now the cloneObject
will not work because the connection
object was shared between them and it was actaually closed by the originalObject
.
假设originalObject
关闭Connection
对象,所以现在cloneObject
将无法工作,因为connection
对象在它们之间共享并且它实际上是由originalObject
.
Similar problem may occur if let say you want to clone a object which has IOStream as a property.
如果假设您要克隆具有 IOStream 作为属性的对象,则可能会出现类似的问题。
How does the recursive cloning happen if the object is a composite object?
如果对象是复合对象,递归克隆如何发生?
Cloneable performs shallow copy. Meaning is that data of original object and clone object will point to the same reference/memory. contrary in the case of deep copy, data from memory of original object is copied to the memory of clone object.
Cloneable 执行浅拷贝。意思是原始对象和克隆对象的数据将指向相同的引用/内存。相反在深拷贝的情况下,原始对象的内存中的数据被复制到克隆对象的内存中。