Защо java.lang.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.


person amicngh    schedule 05.07.2012    source източник
comment
Вижте също: stackoverflow.com/questions/1138769/   -  person assylias    schedule 05.07.2012


Отговори (10)


Тъй като clone е защитен в класа Object. Не е public.

Единственият начин да получите достъп до clone() метода на обект е да знаете, че има тип по време на компилиране, който има публичен clone() метод.

person Louis Wasserman    schedule 05.07.2012
comment
Знам, че е защитен, но защитените методи могат да бъдат достъпни в същия пакет, както и от подкласове и всички класове са дъщерни на java.lang.Object. - person amicngh; 05.07.2012
comment
@amicngh - Не вярвам, че простото подкласиране от клас прави вашия обект автоматично част от същия пакет, нали? - person Steve Townsend; 05.07.2012
comment
@amicngh Съмнявам се, че сте в пакет java.lang и не се обаждате на this.clone(), а на anObject.clone(), така че втората ви точка също не е приложима. - person assylias; 05.07.2012


Това ще бъде минимумът, за да накарате клонирането да работи:

public class SubObj implements Cloneable {
  public Object clone() { return super.clone(); }
}
person Marko Topolnik    schedule 05.07.2012

Полетата protected могат да бъдат достъпни само от вътре в същия пакет, така че clone() методът на Object клас може да бъде достъпен само от всеки клас, който се намира в java.lang пакет.

person Eng.Fouad    schedule 05.07.2012

Трябва изрично да внедрите Cloneable интерфейс. вижте тази тема, която дава обяснения.

person Arcadien    schedule 05.07.2012

Ако използвате 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.

Връзка към API за клониране за java.lang.Object http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29

[РЕДАКТИРАНЕ] Оригиналният въпрос™ попита защо този метод е видим по начина, по който е. Това е така, защото е достъпен само за методи в пакета java.lang. Не е предназначен програмист да може да клонира Object. Хвърлянето на CloneNotSupportedException е точно това, което искате да направите, ако не искате вашият СОБСТВЕН обект да бъде клониран.

person avgvstvs    schedule 05.07.2012

 void method() {

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

}

Не можем да осъществим достъп до защитения метод на връзката „Има A“ от различен пакет, тъй като вашият пакет от клас е (com.xxx.yyy), а пакетът от клас на обект е (java.lang), и двата класа са в различен пакет.

защитените методи могат да бъдат достъпни в същия пакет, както и от подкласове (IS A връзка)

person Ratheesh    schedule 12.08.2014

Опитах този код:

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
    }
}

публичен клас CloneNotSupportedException разширява Exception

Изхвърлено, за да покаже, че методът за клониране в клас Object е бил извикан за клониране на обект, но че класът на обекта не имплементира интерфейса Cloneable. Приложенията, които заместват метода на клониране, също могат да хвърлят това изключение, за да покажат, че даден обект не може или не трябва да бъде клониран.

Обектът не имплементира никакъв интерфейс и за да накара моя потребителски клас да работи, той трябва да имплементира Cloneable

person Adelin    schedule 17.02.2016

Методът 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();
    }
}
person Manoj Ekanayaka    schedule 08.12.2019

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() от peopel обект p1, това не е мястото на peopel обект. myclone() е точно мястото на хората обект.

person andrea wang    schedule 29.08.2020