简体   繁体   English

为什么不能克隆java.lang.Object?

[英]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.因为cloneObject类中是受保护的。 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.

相关问题 为什么java.lang.Object不能转成T? - Why can java.lang.Object no be coverted into T? 我如何在Java中读取Object(java.lang.Object) - how can I read Object (java.lang.Object) in java XmlObject []到java.lang.Object [] - XmlObject [] to java.lang.Object[] 为什么java.lang.Object中的finalize()方法受到“保护”? - Why is the finalize() method in java.lang.Object “protected”? java.lang.Object o = 1; //为什么要编译? - java.lang.Object o = 1;//why does this compile? 为什么在 java.lang.Object 中保护了 clone() 方法? - Why is the clone() method protected in java.lang.Object? 我们可以在java.lang.Object中添加额外的方法吗? - Can we add extra method in java.lang.Object? 找不到引用的方法'com.google.firebase.tasks.Task setValue(java.lang.Object,java.lang.Object)' - can't find referenced method 'com.google.firebase.tasks.Task setValue(java.lang.Object,java.lang.Object)' 可以在子类的对象上调用受保护的方法而不会覆盖它们。 为什么java.lang.Object中的clone方法不同? - Protected methods can be called on the object of subclass without overriding. Why it's different for clone method in java.lang.Object? 为什么java.lang.Cloneable不会覆盖java.lang.Object中的clone()方法? - Why does java.lang.Cloneable not override the clone() method in java.lang.Object?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM