为什么在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的子类obObject
调用以获取正确类的浅表副本
什么样的方法可以被子类调用,但不能被其他类调用?
它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没有任何问题,因为:
-
Object.clone()不会做你想要的自定义类。
-
如果你有Myclass实现Cloneable =>你用“public MyClass clone()”覆盖clone()
-
如果你有MyInterface extends Cloneable和一些实现MyInterface的MyClass:只需定义“public MyInterface clone();” 在接口中,每个使用MyInterface对象的方法都可以克隆它们,不pipe它们是MyClass类。