super.clone() operation not works in Derived Class

谁说胖子不能爱 提交于 2019-12-14 03:56:40

问题


This is raised because of the technical difficulties faced in my Project.

Problem: I need to clone a Object of a Class where it extended the properties(Inheritance) from a third party library class(where we don't have access to modify its contents)

Let me explain with example below:

Parent Class:

public class UnChangeableBaseClass {

  //fields and Methods

}

Child Class:

class DerivedLocalClass extends UnChangeableBaseClass implements Cloneable {

   // local fields and methods


   public Object clone(){

      Object clonedObj= null;

      try{
       clonedObj = super.clone();
      }
      catch(CloneNotSupportedException e){
        //log exceptions
      }

   }

}

When I try to do this, super.clone() method refers to Class - UnChangeableBaseClass Type and it doesn't overrides the Object clone() methods. I believe all classes were extended with java.lang.Object class, implicitly protected Object clone() method would be inherited to this Parent Class. So, i thought in such a way that this method in Derived Class would overrides the Parent/Object clone method. But during runtime JVM search for the clone method explicitly defined in UnChangeableBaseClass. Hope I explained in proper way without confusing you.

My questions are follows:

  1. How can I implement clone method in this typical case, where we cannot add any method
    in parent class to have super.clone() to call Object clone method.

  2. If above case is not possible, is there any other way to clone the Derived Class
    Object (by considering all the limitations in above scenario)

  3. Finally, just to know the reason for this JVM behaviour (described above).


回答1:


Correct Method signature is below

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

Clone is Protected method in Object class so it is accessible to you inside class, and if you are extending from it. super.clone() is just needed to call clone() method from object which calls method internalClone on this which is current class object.

   internalClone((Cloneable) this);

So above clone() method inside Object will only throw CloneNotSupportedException if instance on which it is called is not Cloneable

I see some misconceptions about clone method

  1. clone() method is protected inside Object class so you can not call clone() outside of class. e.g. child.clone() unless you override it and make access public
  2. Cloneable is marker interface and if you do not mark class Cloneable then you will get CloneNotSupportedException if you call clone() method
  3. If a class contains only primitive fields or references to immutable objects, then it is usually the case that no fields in the object returned by super.clone need to be modified.
  4. By convention, the returned object should be obtained by calling super.clone. If a class and all of its superclasses (except Object) obey this convention, it will be the case that x.clone().getClass() == x.getClass().

So below code works fine

public  class Child extends UnChangeableBaseClass
        implements
            Cloneable {

    int index = 0;

    public Child(int index) {

        this.index = 10;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

References :

  1. Object#clone()
  2. Cloneable



回答2:


JVM Cloning works by making use of the Marker interface Cloneable rather than looking for Object.clone(). It is true that all the Java Classes will inherit clone method but according to javadoc for Cloneable

A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.

In your case you can't do super.clone() because it is not marked to be Cloneable. If you cannot change the parent class then you will have to make a Copy of it yourself.




回答3:


How can I implement clone method in this typical case, where we cannot add any method in parent class to have super.clone() to call Object clone method.

Well, since clone method is a protected method in Object class, so it is accessible in your super class UnChangeableBaseClass also, since it extends from Object class. So, basically you can access the clone method, using super.clone(), from your base class DerivedLocalClass.

If above case is not possible, Is there any other way to clone the Derived Class Object (by considering all the limitations in above scenario)

I would suggest, even though you have the option to use clone method to clone the object, you should not use it. It would be better to use a copy-constructor in your derived class, and add a super() call to the base class constructor.

Also, see Effective Java - Item#11 - Override clone judiciously, which suggest that clone method is broken.

In this article: - Josh Bloch on Design - Copy Constructor versus Cloning, you would like to see the very first paragraph of Bloch: -

If you've read the item about cloning in my book, especially if you read between the lines, you will know that I think clone is deeply broken. There are a few design flaws, the biggest of which is that the Cloneable interface does not have a clone method. And that means it simply doesn't work: making something Cloneable doesn't say anything about what you can do with it. Instead, it says something about what it can do internally. It says that if by calling super.clone repeatedly it ends up calling Object's clone method, this method will return a field copy of the original.

So, conclusion is that, you can have a copy constructor in your DerivedLocalClass, which will return you the copy of the invoking object, something like this: -

public DerivedLocalClass(DerivedLocalClass obj) {
    this.setVar(obj.getVar());
}



回答4:


I am using java 1.7 and I don't get any problem in running the code given by OP. Unless the superclass has overridden clone to throw an exception I think this should work even if the superclass does not declare itself clonable.

I will note that

public Object clone()

is not overriding the clone method, its missing the throws clause.



来源:https://stackoverflow.com/questions/13065085/super-clone-operation-not-works-in-derived-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!