clone()
中定义为受保护的具体原因是java.lang.Object
什么?
11 回答
克隆受保护的事实非常可疑 -clone
方法未在Cloneable
接口中声明的事实也是如此。
它使该方法对于获取数据副本毫无用处,因为您不能说:
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 的 Effective Java 的引文:
“Cloneable 接口旨在作为对象的混合接口,以宣传它们允许克隆。不幸的是,它无法达到此目的......这是一种非常不典型的接口使用,不是一个可以模拟的接口...为了实现接口对一个类产生任何影响,它和它的所有超类必须遵守一个相当复杂、不可执行且大部分未记录的协议“
Clonable 接口只是一个标记,表示该类可以支持克隆。该方法受到保护,因为您不应该在对象上调用它,您可以(并且应该)将其覆盖为公共的。
来自太阳:
在 Object 类中,clone() 方法被声明为受保护的。如果您所做的只是实现 Cloneable,那么只有同一个包的子类和成员才能在对象上调用 clone()。要使任何包中的任何类都能访问 clone() 方法,您必须重写它并将其声明为 public,如下所示。(当你重写一个方法时,你可以减少它的私有性,但不能更私有化。这里,Object 中受保护的 clone() 方法被重写为公共方法。)
clone
受到保护,因为它应该被覆盖,以便它特定于当前类。虽然可以创建一个clone
克隆任何对象的公共方法,但这不如专门为需要它的类编写的方法好。
Clone 方法不能直接在任何对象上使用,这就是它打算被子类覆盖的原因。
当然它可以是公开的,并且在无法克隆时抛出适当的异常,但我认为这会产生误导。
现在实现克隆的方式让你思考为什么要使用克隆,以及你希望如何克隆你的对象。
恕我直言,就像这样简单:
#clone
不得在不可克隆的对象上调用,因此不会公开#clone
必须由Object
实现 Cloneable 的子类 ob 调用以获得正确类的浅表副本
应该由子类调用但不能由其他类调用的方法的正确范围是什么?
是protected
。
实现Cloneable
的类当然会将这个方法公开,以便可以从其他类调用它。
它是受保护的,因为默认实现对所有字段(包括私有)进行了浅成员复制,从而绕过了构造函数。这不是一个对象可能被设计为首先处理的事情(例如,它可能会跟踪共享列表中创建的对象实例,或类似的东西)。
出于同样的原因,clone()
如果调用它的对象没有实现Cloneable
. 这是一个具有深远影响的潜在不安全操作,因此该课程的作者必须明确选择加入。
来自可克隆的 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 ,但这在大多数情况下会给您带来不想要的结果或异常。但仅在您实现可克隆时才鼓励使用。
Clone() 方法在内部有一个检查“是否为 Cloneable 的实例”。Java 团队可能认为这将限制对 clone() 方法的不当使用。clone() 方法受到保护,即只能由子类访问。由于 object 是所有子类的父类,因此如果我们没有上面的“可克隆实例”检查,则所有类实际上都可以使用 Clone() 方法。这就是 Java 团队可能考虑通过在 clone() 方法中检查“它是 Cloneable 的实例”来限制不正确使用 clone() 的原因。
因此,任何实现可克隆的类都可以使用 Object 类的 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;
}
}
就像之前有人说的那样。
好吧,sun 开发人员也只是人类,他们确实犯了很大的错误,将克隆方法实现为受保护的,与他们在 ArrayList 中实现无功能的克隆方法一样的错误!因此,一般来说,即使是经验丰富的 Java 程序员也对克隆方法存在更深的误解。
但是,我最近找到了一种快速简便的解决方案,可以复制任何对象及其所有内容,无论它是如何构建的以及它包含什么,请在此处查看我的答案:使用 Object.clone() 中的错误
再次,Java JDK 框架展现了绝妙的思维:
可克隆接口不包含“public T clone();” 方法,因为它的行为更像是一个属性(例如,可序列化),它允许克隆一个实例。
这种设计没有任何问题,因为:
Object.clone() 不会对您的自定义类执行您想要的操作。
如果你有 Myclass 实现 Cloneable => 你用“public MyClass clone()”覆盖 clone()
如果您有 MyInterface extends Cloneable 和一些 MyClasses 实现 MyInterface:只需定义“public MyInterface clone();” 在接口中,每个使用 MyInterface 对象的方法都可以克隆它们,无论它们的 MyClass 类如何。