【问题标题】:is clone() will really clone the interface variable inside an object是 clone() 将真正克隆对象内部的接口变量
【发布时间】:2017-12-12 11:57:51
【问题描述】:

我有一个实现了可克隆接口的类

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);
}

我的问题是我有五个变量而不是接口变量,而克隆所有五个变量正在获取但不是这个接口变量。

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

提前致谢

【问题讨论】:

    标签: java android interface clone


    【解决方案1】:

    我的问题是我有五个变量而不是接口变量,而克隆所有五个变量正在获取但不是这个接口变量。

    这将完全取决于 WiSeConBaseModel 或它与 Object 之间的任何超类是否实现 clone 以及,如果它们实现了,那些 clone 方法会做什么。

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

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

    (我的重点)

    因此,对于Object#clone,该代码将以原始代码和克隆代码结束,它们都通过observer 引用同一个对象。

    【讨论】:

      【解决方案2】:

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

      从概念上讲,这是不对的。
      您不会克隆接口。
      您只克隆实例。
      因此,这意味着在您的情况下,您还希望克隆接口实现。

      我的问题是除了接口变量我还有五个变量 虽然克隆所有五个变量正在获取但不是这个接口 变量。

      这些变量很可能是原语,默认的 clone() 行为是“正常的”,因为原语复制意味着原语赋值,例如 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;
      }
      

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

      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;
      }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-26
        • 2021-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多