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

clone()java.lang.Object被定义为protected是什么原因?

克隆被保护的事实是非常可疑的 – clone方法没有在Cloneable接口中声明。

这使得这个方法对于获取数据的副本来说毫无用处,因为你不能说

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

我认为Cloneable的devise现在在很大程度上被认为是一个错误 (下面引用)。 我通常希望能够实现一个接口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接口的目的是作为一个混合接口,让对象通告它们允许克隆。不幸的是,它无法达到这个目的…这是一个非常非典型的接口使用,而不是一个被模拟的…为了实现接口对类有任何影响,它和它的所有超类必须服从一个相当复杂的,不可执行的,很大程度上没有logging的协议

Clonable接口只是一个标记,表示类可以支持克隆。 该方法是受保护的,因为您不应该在对象上调用它,您可以(也应该)将其覆盖为公共。

从太阳:

在Object类中,clone()方法被声明为protected。 如果您所做的只是实现Cloneable,则只有相同包的子类和成员才能在对象上调用clone()。 要使任何包中的任何类都可以访问clone()方法,就必须覆盖它并将其声明为public,如下所示。 (当你重写一个方法的时候,可以减less私有方法,但是不要使用更多的私有方法,这里,Object中的protected clone()方法被作为一个公共方法重写)。

clone是受保护的,因为它是应该被覆盖的东西,所以它是特定于当前类的。 虽然有可能创build一个克隆任何对象的公共clone方法,但这不会像专门为需要它的类编写的方法那样好。

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

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

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

它受到保护,因为默认实现会对所有字段(包括私有)进行浅层成员复制, 绕过构造函数 。 这不是一个对象可能被devise为首先处理(例如,它可能跟踪共享列表中创build的对象实例,或类似的东西)。

出于同样的原因, clone()的默认实现会抛出,如果它所调用的对象没有实现Cloneable 。 这是一个潜在的不安全的操作,影响深远,因此作者必须明确地selectjoin。

从可复制的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. 

所以你可以调用每一个对象的克隆,但这会给你大部分时间不是你想要的结果或exception。 但是只有在实现可复制的时候才会受到鼓励。

恕我直言,这是这样简单:

  • 不能在不可复制的对象上调用#clone ,因此不公开
  • #clone必须由实现Cloneable的子类ob Object调用以获取正确类的浅表副本

什么样的方法可以被子类调用,但不能被其他类调用?

protected

实现Cloneable的类当然会公开这个方法,所以可以从其他类中调用它。

注意:我不知道java.lang.Object

但是当你的类实现单例typesdevise模式,那么它的强制保护克隆唤醒 构造函数等functionbcz由这些你也可以创build新的实例

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

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

就像以前有人说的那样。

那么,太阳开发者也只是人类,他们确实犯了一个巨大的错误来实现克隆方法作为保护,与他们在ArrayList中实现不起作用的克隆方法相同的错误! 所以,一般来说,即使有经验的Java程序员也会对克隆方法产生更深的误解。

然而,我最近发现了一个快速而简单的解决scheme来复制任何对象的所有内容,无论它是如何构build的,它包含什么,请参阅我的答案: 使用Object.clone()

Java JDK框架再一次展现了出色的思想:

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

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

  1. Object.clone()不会做你想要的自定义类。

  2. 如果你有Myclass实现Cloneable =>你用“public MyClass clone()”覆盖clone()

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