为什么无法克隆java.lang.Object?

时间:2012-07-05 12:56:04

标签: java clone

当我尝试克隆泛型Object时,我得到编译时错误。为什么呢?

    Object obj=new Object();
    obj.clone();  // Here compile time error "The method clone() from the type Object is not visible"

每个类扩展Object类,克隆方法在Object类中受到保护。

protected方法可以在同一个包中访问,也可以在subclasses中访问,所有类都是java.lang.Object的子类。

10 个答案:

答案 0 :(得分:9)

因为clone类中Object 受保护。这不是public

访问对象的clone()方法的唯一方法是知道它具有一个具有公共clone()方法的编译时类型。

答案 1 :(得分:3)

根据Java SE docs

  

类Object本身并不实现Cloneable接口,所以   在类为Object的对象上调用clone方法   导致在运行时抛出异常。

答案 2 :(得分:1)

这将是克隆工作的最低要求:

public class SubObj implements Cloneable {
  public Object clone() { return super.clone(); }
}

答案 3 :(得分:1)

protected个字段只能从同一个包中访问,因此clone()类的Object方法只能从位于java.lang包中的任何类访问

答案 4 :(得分:0)

您必须明确地实现Cloneable接口。 见this thread给出解释。

答案 5 :(得分:0)

如果您使用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]

如果您阅读了克隆API(我将链接它),它表示如果未实现接口,则调用* .clone()将抛出CloneNotSupportedException

链接到java.lang.Object的克隆API http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29

[编辑] Original Question™询问为什么这种方法以其可见方式可见。这是因为它只能访问java.lang包中的方法。程序员不能克隆Object。如果您不希望克隆自己的OWN对象,则抛出CloneNotSupportedException正是您想要做的。

答案 6 :(得分:0)

 void method() {

    Object obj=new Object(); //Object is a parent class, it's not inherit from any other class...     
    obj.clone();        //  compile time error   

}

我们无法从不同的包访问受保护的“Has A”关系方法,因为您的Class包是(com.xxx.yyy)而Object类包是(java.lang)这两个类是不同的封装

受保护的方法可以在同一个包中以及通过子类(IS A关系)访问

答案 7 :(得分:0)

我试过这段代码:

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     扩展异常

  

抛出以指示Object类中的clone方法   调用克隆一个对象,但该对象的类没有   实现Cloneable接口。覆盖的应用程序   clone方法也可以抛出此异常来指示一个对象   不能或不应该克隆。

Object没有实现任何接口,为了使我的User类工作,它必须实现Cloneable

答案 8 :(得分:0)

对象类clone()方法已在API级别由受保护的访问修饰符进行了修改。因此,如果没有继承,我们将无法在任何地方访问它。因此,在调用对象类clone()方法之前,您需要实现Cloneable接口。然后,代码将在运行时正确运行。否则,它将在运行时生成CloneNotSupportedException。

/*Subclass is my implementing class */

public class SubClass implements Cloneable {

    @Override
    public SubClass clone() throws CloneNotSupportedException {
        return (SubClass) super.clone();
    }
}

答案 9 :(得分:0)

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();
        
    }
}

请参阅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();

为什么? 原因test()不属于子类。 因此,即使有人对象clone()调用p1,也不是peopel对象的位置。 myclone()正是人们所反对的地方。