为什么 clone()方法在 java.lang.Object 中受到保护?

clone()java.lang.Object中被定义为受保护的具体原因是什么?

56720 次浏览

clone受到保护,因为它是应该被重写的内容,以便它是特定于当前类的。虽然有可能创建一个公共 clone方法来克隆任何对象,但这不如专门为需要它的类编写的方法好。

The fact that clone is protected is extremely dubious - as is the fact that the clone method is not declared in the Cloneable interface.

It makes the method pretty useless for taking copies of data because 你不能说:

if(a instanceof Cloneable) {
copy = ((Cloneable) a).clone();
}

我认为 Cloneable的设计现在是 在很大程度上被认为是一个错误(引用如下)。我通常希望能够实现接口 Cloneable但是 不一定使接口 Cloneable(类似于使用 Serializable)。这不可能不经过深思熟虑就做到:

ISomething i = ...
if (i instanceof Cloneable) {
//DAMN! I Need to know about ISomethingImpl! Unless...
copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}

引自 Josh Bloch 的高效 Java:
”Cloneable 接口的目的是作为一个 Mixin 接口,用于对象宣传它们允许克隆。不幸的是,它没有达到这个目的... ... 这是接口的一个高度非典型的使用,而不是一个被模仿... ... 为了实现接口对类有任何影响,它和它的所有超类必须服从 相当复杂,不可执行,大部分没有文件记录的协议

Clone 方法不能直接用于任何对象,这就是为什么它要被子类重写的原因。

当然,它可以是公开的,只是抛出一个适当的例外,当克隆是不可能的,但我认为这将是误导。

现在实现克隆的方式让您思考为什么要使用克隆,以及如何克隆对象。

它之所以受到保护,是因为默认实现对所有字段(包括私有字段) 规避构造函数规避构造函数执行浅层成员复制。这不是一个对象最初可能被设计用来处理的事情(例如,它可能会在共享列表中跟踪已创建的对象实例,或者类似的事情)。

出于同样的原因,如果调用它的对象没有实现 Cloneable,则 clone()的默认实现将抛出。这是一个潜在的不安全操作,具有深远的影响,因此类的作者必须显式地选择加入。

从 javadoc 的克隆。

* By convention, classes that implement this interface (cloneable) should override
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.


* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface.  Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.

所以你可以在每个对象上调用 clone,但是这会给你大部分时间,不是你想要的结果或者异常。但只有在实现可克隆的。

Clological 接口只是一个标记,表明该类可以支持克隆。该方法受到保护,因为您不应该在对象上调用它,您可以(并且应该)将其作为公共重写。

来自 Sun:

在 Object 类中,clone ()方法被声明为 protected。如果您所做的只是实现 Cloneable,那么只有同一个包的子类和成员能够在对象上调用 Cloneable ()。要使任何包中的任何类都能访问  ()方法,必须重写它并声明它为 public,如下所示。(当重写方法时,可以降低它的私有性,但不能提高它的私有性。在这里,Object 中的 protected clone ()方法作为公共方法被重写。)

是的,和我遇到的问题一样。 但是我通过实现这个代码来解决它

public class Side implements Cloneable {
public Side clone() {


Side side = null;
try {
side = (Side) super.clone();
} catch (CloneNotSupportedException e) {
System.err.println(e);
}
return side;
}
}

Just as the before someone said.

同样,Java JDK 框架展示了卓越的思维:

可克隆接口不包含“ public T clone () ;”方法,因为它的作用更像一个属性(例如。序列化) ,它允许克隆一个实例。

这种设计没有任何问题,因为:

  1. Clone ()不会对自定义类执行您想要的操作。

  2. If you have Myclass implements Cloneable => you overwrite clone() with “公共 MyClass 克隆()”

  3. 如果你有 MyInterface 扩展 Cloneable 和一些实现 MyInterface 的 MyClass: 只需在接口中定义“ public MyInterface  () ;”,使用 MyInterface 对象的每个方法都可以克隆它们,不管它们的 MyClass-class 是什么。

好吧,太阳开发者也只是人类,他们确实犯了一个巨大的错误来实现受保护的克隆方法,就像他们在数组列表中实现了一个不起作用的克隆方法一样!因此,一般来说,对于克隆方法,即使是经验丰富的 Java 程序员也存在着更深层次的误解。

然而,我最近发现了一个快速简单的解决方案,可以复制任何对象及其所有内容,无论它是如何构建的,包含什么内容,请看我的答案: 使用 Object.clone ()时出现错误

恕我直言,事情就是这么简单:

  • 不能对不可克隆的对象调用 #clone,因此它不会公开
  • #clone必须由实现 Cloneable 的子类 ob Object调用,以获得正确类的浅表副本

对于子类可以调用但其他类不能调用的方法,正确的范围是什么?

protected

实现 Cloneable的类当然会将此方法公开,以便可以从其他类调用它。

Clone() method has a check internally 'instance of Cloneable or not'.This is how Java team might thought will restrict the improper use of clone() method.clone() method is protected i.e. accessed by subclasses only. Since object is the parent class of all sub classes, so Clone() method can be used by all classes infact if we don't have above check of 'instance of Cloneable'. This is the reason Java team might have thought to restrict the improper use of clone() by having the check in the clone() method 'is it instance of Cloneable'.

因此,任何实现可克隆的类都可以使用 Object 类的 clone ()方法。

此外,因为它是受保护的,它只对那些实现可克隆接口的子类可用。如果我们想让它公开,这个方法必须被子类用它们自己的实现重写。