在有效的
Java中,作者指出:
If a class implements Cloneable,
Object’s clone method returns a
field-by-field copy of the object;
otherwise it throws
CloneNotSupportedException.
我想知道的是他的逐场复制的意思.这是否意味着如果该类在内存中有X个字节,那么它只会复制一段内存?如果是,那么我可以假设原始类的所有值类型将被复制到新对象吗?
class Point implements Cloneable{ private int x; private int y; @Override public Point clone() { return (Point)super.clone(); } }
如果Object.clone()做的是Point类的字段副本,我会说我不需要显式地复制字段x和y,因为上面显示的代码将足够多Point类的一个克隆.也就是说,以下代码是冗余的:
@Override public Point clone() { Point newObj = (Point)super.clone(); newObj.x = this.x; //redundant newObj.y = this.y; //redundant }
我对吗?
我知道克隆对象的引用将自动指向原始对象的引用指向的位置,我只是不确定特定于值类型的情况.如果有人可以清楚的说明Object.clone()的算法规范(简单的语言),那将是很棒的.
解决方法
是的,按字段复制的字段意味着当它创建新的(克隆的)对象时,JVM会将每个字段的值从原始对象复制到克隆的对象中.不幸的是,这意味着你有一个浅的副本.如果你想要一个深层次的拷贝,你可以覆盖克隆方法.
class Line implements Cloneable { private Point start; private Point end; public Line() { //Careful: This will not happen for the cloned object SomeGlobalRegistry.register(this); } @Override public Line clone() { //calling super.clone is going to create a shallow copy. //If we want a deep copy,we must clone or instantiate //the fields ourselves Line line = (Line)super.clone(); //assuming Point is cloneable. Otherwise we will //have to instantiate and populate it's fields manually line.start = this.start.clone(); line.end = this.end.clone; return line; } }
还有一个关于克隆的另一个重要的事情是,克隆对象的构造函数从不被调用(仅复制字段).因此,如果构造函数初始化外部对象,或者使用某些注册表注册此对象,则克隆对象不会发生.
我个人更喜欢不使用Java的克隆.相反,我通常会创建自己的“重复”方法.