在有效的Java中,作者指出:

如果类实现可克隆,则对象的克隆方法将返回对象的视野副本;否则,它会引发clonotsupportedException。

我想知道的是他对视野副本的含义。这是否意味着,如果类中有X字节,则只会复制该内存?如果是,那么我可以假设原始类的所有值类型都将被复制到新对象中吗?

class Point implements Cloneable{
    private int x;
    private int y;

    @Override
    public Point clone() {
        return (Point)super.clone();
    }
}

如果是什么 Object.clone() 做是按字段副本的字段副本 Point 上课,我会说我不需要明确复制字段 xy, ,因为上面显示的代码将足以制作克隆 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的克隆。相反,我通常会创建自己的“重复”方法。

其他提示

这意味着浅副本 - 字段已复制,但是如果您有任何参考,则没有复制这些指示 - 您将有两个引用对同一对象的引用,一个在旧对象中,一个在新的对象中目的。但是,对于具有原始类型的字段,该字段是数据本身,因此无论如何它们都会被复制。

newObj.x = this.x; //redundant
newObj.y = this.y; //redundant

没错 - 这些是多余的,因为它们已经通过对象的clone()方法复制了。

将其视为数据副本是正确的。复制原始类型,也会复制引用,因此它们指向相同的对象。例如,

class A implements Cloneable {
  Object someObject;
}

A a = new A();
a.someObject = new Object();

A cloneA = (A)a.clone();
assert a.someObject==cloneA.someObject;

默认克隆执行值的浅副本。对于原始值,这足够,不需要额外的工作。

对于对象,浅副本意味着仅复制引用。因此,在这些情况下,通常需要深层副本。例外是当引用指向不变的对象时。不变的物体不会改变其明显的状态,因此可以安全地复制其参考。例如,这适用于字符串,整数,浮点,枚举(如果不能错误地变形)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top