[英]Why java.lang.Object can not be cloned?
When i try to clone a generic Object i get compile time error.当我尝试克隆一个通用对象时,出现编译时错误。 why?
为什么?
Object obj=new Object();
obj.clone(); // Here compile time error "The method clone() from the type Object is not visible"
Every class extends Object class and clone method is protected in Object class.每个类都扩展了Object类,克隆方法在Object类中受到保护。
protected
methods can be accessed in same package as well as by subclasses
and all classes are child of java.lang.Object
. protected
的方法可以在同一个包中访问,也可以通过subclasses
访问,所有类都是java.lang.Object
的子类。
Because clone
is protected in the Object
class.因为
clone
在Object
类中是受保护的。 It's not public
.这不是
public
的。
The only way to get access to an object's clone()
method is to know it has a compile-time type that has a public clone()
method.访问对象的
clone()
方法的唯一方法是知道它有一个具有公共clone()
方法的编译时类型。
This will be the minimum to get clone working:这将是让克隆工作的最低限度:
public class SubObj implements Cloneable {
public Object clone() { return super.clone(); }
}
Per the Java SE docs :根据Java SE 文档:
The class Object does not itself implement the interface Cloneable, so calling the clone method on an object whose class is Object will result in throwing an exception at run time.
Object 类本身并没有实现 Cloneable 接口,因此在类为 Object 的对象上调用 clone 方法将导致在运行时抛出异常。
protected
fields can be accessed only from inside the same package, thus clone()
method of Object
class can be accessed only from any class that is located in java.lang
package. protected
的字段只能从同一个包内部访问,因此只能从位于java.lang
包中的任何类访问Object
类的clone()
方法。
You must explicitely implements Cloneable interface.您必须显式实现 Cloneable 接口。 see this thread which give explanations.
请参阅此线程,其中给出了解释。
If you use Groovy so that you can bypass the java compilation error, you get this:如果你使用 Groovy 这样你就可以绕过 java 编译错误,你会得到这个:
Exception in thread "main" java.lang.CloneNotSupportedException: java.lang.Object
at java.lang.Object.clone(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:230)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:912)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:756)
at org.codehaus.groovy.runtime.InvokerHelper.invokePojoMethod(InvokerHelper.java:766)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:754)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:170)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethod0(ScriptBytecodeAdapter.java:198)
at regexTests.main(regexTests.groovy:19)
ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2
JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [../../../src/share/back/util.c:820]
If you read the clone API (I will link it) it says that if the Interface isn't implemented, then calling *.clone() will throw a CloneNotSupportedException
.如果您阅读克隆 API(我将链接它),它会说如果未实现接口,则调用 *.clone() 将抛出
CloneNotSupportedException
。
Link to the clone API for java.lang.Object
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29链接到
java.lang.Object
的克隆 API http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29
[EDIT] The Original Question™ asked for why this method is visible in the way it is. [编辑] Original Question™ 问了为什么这个方法以它现在的方式可见。 This is because it only accessible to methods within the java.lang package.
这是因为它只能由 java.lang 包中的方法访问。 It isn't intended for a programmer to be able to clone an
Object
.它不是为了让程序员能够克隆
Object
。 Throwing a CloneNotSupportedException
is exactly what you want to do if you don't want your OWN object cloned.如果您不想克隆您的 OWN 对象,那么抛出
CloneNotSupportedException
正是您想要做的。
void method() {
Object obj=new Object(); //Object is a parent class, it's not inherit from any other class...
obj.clone(); // compile time error
}
We can't access the protected method of "Has A" relationship from different package, because your Class package is (com.xxx.yyy) and an Object class package is (java.lang) both the classes are in different package.我们无法从不同的包访问“Has A”关系的受保护方法,因为您的类包是 (com.xxx.yyy) 和对象类包是 (java.lang) 这两个类在不同的包中。
protected methods can be accessed in same package as well as by subclasses(IS A relationship)受保护的方法可以在同一个包中访问,也可以通过子类访问(是一种关系)
I tried this code:我试过这段代码:
public final class User {
private String name;
private boolean isActive;
private String userId;
private Address address;
// can be constructed using this constructor ONLY !
public User(String name, boolean isActive, String userId, Address address) {
this.name = name;
this.isActive = isActive;
this.userId = userId;
this.address = address;
}
public String getName() {
return name;
}
public boolean isActive() {
return isActive;
}
public String getUserId() {
return userId;
}
public Address getAddress() {
return address;
}
protected Object cloneMe() throws CloneNotSupportedException {
return super.clone(); // throws CloneNotSupportedException
}
}
public class CloneNotSupportedException extends Exception公共类 CloneNotSupportedException 扩展异常
Thrown to indicate that the clone method in class Object has been called to clone an object, but that the object's class does not implement the Cloneable interface.
抛出表示类 Object 中的 clone 方法已被调用以克隆对象,但该对象的类未实现 Cloneable 接口。 Applications that override the clone method can also throw this exception to indicate that an object could not or should not be cloned.
覆盖克隆方法的应用程序也可以抛出此异常以指示不能或不应克隆对象。
Object doesn't implement any interface and to make my User class work it must implement Cloneable
对象不实现任何接口,要使我的 User 类工作,它必须实现
Cloneable
Object class clone() method has modified by protected access modifier in the API level.对象类 clone() 方法已被 API 级别的受保护访问修饰符修改。 So we can't access it anywhere without inheritance.
所以我们不能在没有继承的情况下在任何地方访问它。 So before we invoke object class clone() method you need to implements Cloneable interface.
因此,在我们调用对象类的 clone() 方法之前,您需要实现 Cloneable 接口。 Then Code will run at runtime properly.
然后代码将在运行时正常运行。 Otherwise it will generate CloneNotSupportedException at runtime.
否则它将在运行时生成 CloneNotSupportedException。
/*Subclass is my implementing class */
public class SubClass implements Cloneable {
@Override
public SubClass clone() throws CloneNotSupportedException {
return (SubClass) super.clone();
}
}
import java.util.Scanner;
import java.util.jar.Attributes.Name;
import java.util.Arrays;
public class Main{
public class man{
protected void name() {
System.out.println("hei");
}
}
public class people extends man{
public int age;
public int getAge() {
name();
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "people [age=" + age + "]";
}
public Object myclone() throws CloneNotSupportedException {
return this.clone();
}
}
public void test() throws CloneNotSupportedException {
people p1 = new people();
p1.setAge(10);
System.out.println(p1);
// NG:
people p2 = (people)p1.clone();
// Ok
people p3 = (people)p1.myclone();
p1.setAge(10);
System.out.println(p1);
System.out.println(p2);
}
public static void main(String args[]) throws CloneNotSupportedException{
new Main().test();
}
}
see the NG code and ok code.查看 NG 代码和 ok 代码。
// NG for:The method clone() from the type Object is not visible
people p2 = (people)p1.clone();
// Ok
people p3 = (people)p1.myclone();
why?为什么? cause
test()
is not belong to the subclass.因为
test()
不属于子类。 so even though call clone()
by peopel object p1
,it is not the place of peopel
object.所以即使通过 peopel 对象
p1
调用clone()
,它也不是peopel
对象的地方。 The myclone()
is the exactly the place of people object. myclone()
正是 people 对象所在的位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.