是clone()将真正克隆对象内的接口变量

时间:2017-12-12 11:57:51

标签: java android interface clone

我有一个实现了clonable接口的类

public class BaseModelItem extends WiSeConBaseModel implements Cloneable{
private ValueChangeObserver observer=null;

//setting interface other values here

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

界面看起来

public interface ValueChangeObserver {
onChanged(Object obj);
}

我的问题是我有五个变量而不是接口变量,而克隆所有五个变量都得到了但不是这个接口变量。

是否存在克隆接口对象或任何其他问题的问题?

提前致谢

2 个答案:

答案 0 :(得分:1)

  

我的问题是我有五个变量而不是接口变量,而克隆所有五个变量都得到了但不是这个接口变量。

这完全取决于WiSeConBaseModelObjectclone之间的任何超类是否实现clone,以及Object#clone方法执行的操作。< / p>

如果他们,则使用Object#clone。文档说:

  

Object类的方法clone执行特定的克隆操作。首先,如果此对象的类未实现Cloneable接口,则抛出CloneNotSupportedException。请注意,所有数组都被认为实现了Cloneable接口,并且数组类型T []的clone方法的返回类型是T [],其中T是任何引用或基本类型。否则,此方法创建此对象的类的新实例,并使用该对象的相应字段的内容初始化其所有字段,就像通过赋值一样;这些字段的内容本身不会被克隆。 因此,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作。

(我的重点)

因此,对于observer,该代码将以原始代码和克隆结束,并通过indexTitles(for:)引用同一对象。

答案 1 :(得分:1)

  

是否存在克隆接口对象或任何其他对象的问题   问题

从概念上讲,这是不对的 你不克隆接口 您只克隆实例 所以这意味着在你的情况下你也想要克隆接口实现。

  

我的问题是我有五个变量而不是接口变量   虽然克隆所有五个变量但是没有这个接口   变量

这些变量很可能是原语,默认的clone()行为是&#34;罚款&#34;原语复制意味着原始分配,例如clone.myInt = original.myInt,这不会导致原始和克隆对象之间的共享myInt变量。

但是这个:

private ValueChangeObserver observer = null;

不是原始的。

因此,当您克隆BaseModelItem实例时,observer字段将引用原始对象和克隆对象中的完全相同的对象。

因此,您应该指定如何克隆该变量 你应该写一些类似的东西:

private ValueChangeObserver observer = null;
...
@Override
public WiSeConBaseModelItem clone() {
    WiSeConBaseModelItem clonedItem = (WiSeConBaseModelItem) super.clone();
    cloneItem.observer = observer.clone();
    return clonedItem;
}

因此,这意味着您必须在clone()的每个实施中覆盖ValueChangeObserver,但您还必须在clone()中定义ValueChangeObserver,因为它不会声明:

public interface ValueChangeObserver {
   onChanged(Object obj);
}

事实上,您甚至不应该使用clone()Cloneable() 所有这一切都应该让你意识到覆盖clone()是复杂的,容易出错(并且它对可变类包含的final字段也有一个重要的限制,因为你无法重新分配final字段。

所以请忘记clone(),而不是使用复制构造函数:

public WiSeConBaseModelItem copy() {
     WiSeConBaseModelItem copy = new WiSeConBaseModelItem(primitiveOne, primitiveTwo, primitiveThree, observer.copy() ...);
     return copy;
}

您也可以使用反射库来执行复制 它避免编写锅炉板代码 请注意,处理时间可能更重要一些。所以应该考虑它。