我尝试使用以下代码来克隆对象。编译时显示克隆受保护且无法访问,但我有扩展的Object类,因此克隆方法将公开给我的类。请解释原因。
class storeDate extends Object {
public static void main(String[] args)
{
storeDate d = new storeDate();
Object o = (storeDate)d;
o.clone():
}
}
编译时我收到此错误
clone()在java.lang.Object中具有受保护的访问权限 kkk.clone();
答案 0 :(得分:1)
您应该从Object覆盖并实现clone方法。然后,如果您需要clone()
中的方法正文,则可以致电super.clone()
或Object.clone
。标准实现只是克隆了原始类型和对其他对象的引用。
子类需要实现接口Cloneable
(它只是一个没有方法可以实现的标记接口)。
(回到你的问题)对象本身不可克隆(不实现Cloneable),因此无法克隆。并且因为Object#clone
被实现为受保护的方法,所以Object
的任何子类(实际上=每个类)都可以访问其继承的clone()
方法以及'java.lang {{中的每个类。 1}} clone()`来自其他对象的方法。
要快速了解修饰符,请参阅此nice matrix。
答案 1 :(得分:1)
你绝对必须使用clone
吗?大多数人都同意Java clone
已被破坏。
Josh Bloch on Design - Copy Constructor versus Cloning
如果您已经阅读了我的书中有关克隆的内容,特别是如果您在这些内容之间进行了阅读,您会发现我认为
clone
已经被彻底打破了。 [...]Cloneable
被打破是一种耻辱,但它确实发生了。
您可以在他的书 Effective Java 2nd Edition,Item 11:明智地覆盖clone
中阅读有关该主题的更多讨论。他建议改为使用复制构造函数或复制工厂。
他接着写了一些页面,说明如果你认为必须如何,你应该实施clone
。但他以此结束了:
所有这些复杂性真的有必要吗?很少。如果扩展实现
Cloneable
的类,除了实现行为良好的clone
方法之外别无选择。否则,您最好提供替代的对象复制方法,或者根本不提供该功能。
重点是他,而不是我的。必须阅读整个项目以更深入地了解问题并考虑替代方案。
以下是本书的引用:
对象复制的一个很好的方法是提供复制构造函数或复制工厂。
在这种情况下,可以通过提供另一个StoreDate
的{{1}}构造函数或提供实用程序方法StoreDate
来实现它。
答案 2 :(得分:1)
关键是这些类属于哪个包。
JLS paragraph 6.6.2中解释了这一点:
6.6.2有关受保护访问的详细信息
对象的受保护成员或构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明。
示例:
无法编译:
FILE pkg1 / A.java (对应于您问题中的Object类)
package pkg1;
public class A {
protected void method() {};
}
FILE pkg2 / B.java (对应于你问题中的storeDate)
package pkg2;
import pkg1.A;
public class B extends A {
public static void main(String args[]) {
new A().method();
}
}
javac
输出以下内容:
pkg2/B.java:5: method() has protected access in pkg1.A
new A().method();
^
(类似于你所拥有的: clone()在java.lang.Object中具有受保护的访问权限kkk.clone(); )
只需将B
移至pkg1
包即可解决问题。
也就是说,会编译:
FILE pkg1 / A.java (未更改)
package pkg1;
public class A {
protected void method() {};
}
FILE pkg1 / B.java (从pkg2移到pkg1)
package pkg1; // Changed from pkg2
//import pkg1.A; // Not necessary anymore.
public class B extends A {
public static void main(String args[]) {
new A().method();
}
}
那么,您需要做什么才能做new Object().clone()
之类的事情?好吧,你必须属于java.lang
包(反过来会导致SecurityException: Prohibited package name: java.lang
)。