【问题标题】:What is the point of the cloneable interface?可克隆接口的意义何在?
【发布时间】:2015-03-30 04:56:20
【问题描述】:

Java 中可克隆接口的意义何在? java中的核心对象有一个clone()方法。你能不直接覆盖那个方法吗?:

@Override
public Foo clone(){
    return new Foo(this.x, this.y);
}

请解释您为什么要使用该界面。我已经知道克隆对象的来龙去脉。我只是不明白你为什么要使用这个界面。

【问题讨论】:

  • About Java cloneable 的可能重复项
  • @KennethClark 好吧,这更多是关于一般克隆以及为什么要使用它..

标签: java interface


【解决方案1】:

要回答您的第一个问题,您必须实现Clonable 接口才能使clone() 方法工作,因为Object 的克隆会检查该接口是否已实现,否则会抛出异常。

使用clone() 是个坏主意。这是 Java 中最初的想法之一,但没有成功。存在一些设计问题,包括它通常是浅拷贝。如果要对对象进行复制或深复制,最好创建一个复制构造函数或复制方法来执行此操作,而无需使用克隆。正确使用 clone() 很难。

如果您真的想使用clone(),请阅读this blog post,其中解释了如何使用clone()。使用clone()时基本上有5点要记住:

1) Clone 方法用于在 Java 中创建对象的副本。为了使用 clone() 方法,类必须实现 java.lang.Cloneable 接口并覆盖 java.lang.Object 中受保护的 clone() 方法。如果该类未实现 Cloneable 接口,则调用 clone() 方法将导致 CloneNotSupportedException。

2) 在 Java 中克隆 Object 时不调用构造函数。

3) Java 中 clone() 方法的默认实现提供对象的“浅拷贝”,因为它通过创建新实例然后通过赋值复制内容来创建 Object 的副本,这意味着如果您的 Class 包含可变字段,那么原始对象和克隆都将引用相同的内部对象。这可能很危险,因为对该可变字段所做的任何更改都会反映在原始对象和副本对象中。为了避免这种情况,请重写 clone() 方法以提供对象的深层副本。

4) 按照惯例,实例的克隆应该通过调用 super.clone() 方法获得,这将有助于保持由 clone() 方法创建的对象的不变性,即 clone != original 和 clone.getClass() = = original.getClass()。虽然这些并不是 Javadoc 中提到的绝对要求。

5) 实例的浅拷贝是可以的,直到它只包含原语和不可变对象,否则,您需要修改 super.clone 返回的对象的一个​​或多个可变字段,然后再将其返回给调用者。

【讨论】:

    【解决方案2】:

    Java Docs中提到的:

    A class implements the Cloneable interface to indicate 
    to the Object.clone() method that it is legal for that method 
    to make a field-for-field copy of instances of that class.
    

    具体来说:

    Invoking Object's clone method on an instance that does not 
    implement the Cloneable interface results in the exception
    CloneNotSupportedException being thrown.
    

    如果您有任何问题,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 2016-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-07
      • 1970-01-01
      相关资源
      最近更新 更多