如何使用clone()方法克隆Java对象
我不明白克隆自定义对象的机制。例如:
public class Main{
public static void main(String [] args) {
Person person = new Person();
person.setFname("Bill");
person.setLname("Hook");
Person cloned = (Person)person.clone();
System.out.println(cloned.getFname() + " " + cloned.getLname());
}
}
class Person implements Cloneable{
private String fname;
private String lname;
public Object clone() {
Person person = new Person();
person.setFname(this.fname);
person.setLname(this.lname);
return person;
}
public void setFname(String fname) {
this.fname = fname;
}
public void setLname(String lname){
this.lname = lname;
}
public String getFname(){
return fname;
}
public String getLname() {
return lname;
}
}
这个例子展示了书中所写的正确的克隆方法。但我可以删除类名定义中的 Implements Cloneable,并且收到相同的结果。
所以我不明白Cloneable的提议以及为什么clone()方法被定义在类Object中?
I don't understand the mechanism of cloning custom object. For example:
public class Main{
public static void main(String [] args) {
Person person = new Person();
person.setFname("Bill");
person.setLname("Hook");
Person cloned = (Person)person.clone();
System.out.println(cloned.getFname() + " " + cloned.getLname());
}
}
class Person implements Cloneable{
private String fname;
private String lname;
public Object clone() {
Person person = new Person();
person.setFname(this.fname);
person.setLname(this.lname);
return person;
}
public void setFname(String fname) {
this.fname = fname;
}
public void setLname(String lname){
this.lname = lname;
}
public String getFname(){
return fname;
}
public String getLname() {
return lname;
}
}
This is example shows right way of cloning as a in the books write. But I can delete implements Cloneable in the class name definition and I receive the same result.
So I don't understand the proposing of Cloneable and why clone() method is defined in class Object?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
克隆方法旨在进行深层复制。确保您了解深拷贝和浅拷贝之间的区别。在您的情况下,复制构造函数可能是您想要的模式。然而,在某些情况下,您不能使用此模式,例如,因为您正在子类化 X 类,并且您无权访问所需的 X 构造函数。如果 X 正确地重写了其克隆方法(如有必要),那么您可以通过以下方式进行复制:
一般情况下,重写克隆方法时:
super.clone()
clone()
也适用于任何子类时,不要包含 throws 子句(克隆模式的弱点;如果可能,将类设为 Final)super.clone()
(克隆模式的另一个弱点,因为这些字段无法最终确定)Object
的clone()
方法(当所有超类遵守契约时最终将被调用)创建浅拷贝并处理新对象的正确运行时类型。注意整个过程中没有调用构造函数。如果您希望能够在实例上调用
clone()
,请实现Cloneable
接口并将该方法公开。如果您不想在实例上调用它,但确实希望确保子类可以调用它们的 super.clone() 并获取它们所需的内容,那么就不要实现 < code>Cloneable 并保持该方法protected
(如果您的超类尚未将其声明为 public)。克隆模式很困难并且有很多陷阱。确保这是您所需要的。考虑复制构造函数或静态工厂方法。
The clone method is meant to make a deep copy. Make sure you understand the difference between deep and shallow copies. In your case a copy constructor may be the pattern you want. In some cases you can't use this pattern however, for example because you're subclassing class X and you don't have access to the constructor of X that you need. If X overrides its clone method correctly (if necessary) then you could make a copy in the following way:
In general when overriding your clone method:
super.clone()
clone()
will also work for any subclass (weakness of the clone-pattern; make class final if possible)super.clone()
(another weakness of the clone-pattern, since these fields cannot be made final)The
clone()
method ofObject
(which will eventually be called when all superclasses obey the contract) makes a shallow copy and takes care of the correct runtime type of the new object. Note how no constructor is called in the entire process.If you want to be able to call
clone()
on instances, then implement theCloneable
interface and make the method public. If you don't want to be able to call it on instances, but you do want to make sure subclasses can call theirsuper.clone()
and get what they need, then don't implementCloneable
and keep the methodprotected
if your superclass hasn't declared it public already.The clone pattern is difficult and has a lot of pitfalls. Be sure it's what you need. Consider copy constructors, or a static factory method.
JVM 能够为您克隆对象,因此您不应该自己构造一个新对象。只需使用以下代码:
或
即使 Person 类是子类化的,这也会起作用,而您的克隆实现将始终创建 Person 的实例(例如,而不是为 Employee 创建 Employee 的实例)。
The JVM is able to clone the object for you, and you're thus not supposed to construct a new person by yourself. Just use this code:
or
This will work even if the Person class is subclassed, whereas your clone implementation will always create an instance of Person (and not an instance of Employee for an Employee, for example).
Object
类中的clone()
对内存进行浅表复制,而不是调用构造函数等方法。为了在任何本身没有实现clone()
的对象上调用clone()
,您需要实现Clonable
接口。如果您重写
clone()
方法,则不必实现该接口。正如 JavaDoc 所说,这将导致异常:
如果示例中的
A
将实现Clonable
调用clone()
(A
>Object 版本)将生成一个新的A
实例,该实例引用完全相同 StringBuilder,即对克隆中的sb
进行更改实例将导致sb
中的更改原始A
实例。这意味着浅拷贝,这也是为什么通常最好重写
clone()
的原因之一。编辑:作为旁注,使用返回类型协方差将使您的重写
clone()
更加明确:The
clone()
in classObject
does a shallow copy of the memory instead of calling methods like the constructor. In order to callclone()
on any object that doesn't implementclone()
itself, you need to implement theClonable
interface.If you override the
clone()
method you don't have to implement that interface.Just as the JavaDoc says, this would result in an exception:
If
A
in the example would implementClonable
callingclone()
(theObject
version) would result in a newA
instance that references the very same StringBuilder, i.e. changes tosb
in the cloned instance would result in changes to thesb
in the originalA
instance.That's meant with a shallow copy and that one reason why it is generally better to override
clone()
.Edit: just as a sidenote, using return type covariance would make your overridden
clone()
more explicit:克隆并不成熟,正如 Joshua bloch 所说:
http://www.artima.com/intv/bloch13。 html
clone is not mature as Joshua bloch say:
http://www.artima.com/intv/bloch13.html
无需在
clone()
方法中显式创建对象。只需调用 super.clone() 即可创建该对象的副本。它将执行浅克隆。There's no need to create the object explicitly here in
clone()
method. Just by callingsuper.clone()
will create the copy of this object. It will perform the shallow clone.它的目的与任何此类接口相同。首先,它允许方法(等)接受任何 Clonable 对象并可以访问它们所需的方法,而无需将自己限制为一个特定对象。诚然,Clonable 可能是这方面不太有用的接口之一,但肯定有一些地方您可能需要它。如果您想要更多想法,请考虑接口 Comparable,例如,它允许您对列表进行排序(因为列表不需要知道对象是什么,只需知道它们可以进行比较)。
It's the same purpose as any such interface. Primarily it allows methods (etc.) to accept ANY Clonable object and have access to the method they need without limiting themselves to one specific object. Admittedly Clonable is probably one of the less useful interfaces in this respect, but there's certainly places where you might want it. If you want more of an idea consider the interface Comparable which for example allows you to have sorted lists (because the list doesn't need to know what the object is, only that they can be compared).
如果你没有声明可克隆接口,那么当你调用克隆方法时,你应该得到 CloneNotSupportException。如果你声明然后调用克隆方法,它将进行浅复制。
if you dont declare cloneable interface you should be getting CloneNotSupportException when you call clone method.If you declare and then call clone method it will make shallow copy.
在您的示例中,您没有进行实际的克隆。您被覆盖了对象类的clone()方法并给出了您自己的实现。但在您的克隆方法中,您正在创建一个新的 Person 对象。并返回它。所以在这种情况下,实际对象没有被克隆。
所以你的克隆方法应该是这样的:
所以这里克隆将由超类方法处理。
In your example you are not doing actual cloning.you are overridden the clone() method of object class and given your own implementation. but in your clone method you are creating a new Person object. and returning it.So in this case the actual object is not cloned.
So your clone method should be like :
So here clone will be handled by superclass method.