Super.clone () operation does not work in derived class

This is due to technical difficulties encountered in my project.

Problem: I need to clone a class object in which it has extended properties (inheritance) from a third party library class (where we don't have access to change its content).

Let me clarify 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, the method super.clone()

is of type Class - UnChangeableBaseClass

and does not override the methods Object clone()

. I believe all classes were extended with java.lang.Object class

, implicitly the protected Object clone()

method would be inherited for that parent class. So, I figured this method in Derived Class would override the parent / object cloning method. But at runtime, the JVM looks for a clone method explicitly defined in UnChangeableBaseClass

. I hope I explained correctly, not to confuse you.

My questions:

  • How can I implement the clone method in this typical case where we cannot add any method in the parent class to super.clone()

    call the object clone method.

  • If the above case is not possible, is there another way to clone the derived class Object (considering all the limitations in the above scenario)

  • Finally, just to find out the reason behind this JVM behavior (described above).

+2


source to share


4 answers


The correct method signature is below

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

      

Clone is a method Protected

in a class Object

, so it is available to you inside the class, and if you extend from it. super.clone()

you just need to call the method clone()

from the object that calls the internalClone

on method this

, which is the current class object.

   internalClone((Cloneable) this);

      

So the above clone()

method inside Object

will only throw CloneNotSupportedException

if the instance it is being called on is notCloneable

I see some misconceptions about the cloning method



  • clone()

    the method is Protected

    inside the class Object

    , so you cannot call clone()

    outside the class. for example child.clone()

    , if you don't override it and make accesspublic

  • Cloneable

    is a marker interface and if you do not mark the class Cloneable

    then you will get CloneNotSupportedException

    if you call the methodclone()

  • If the class contains only primitive fields or references to immutable objects, then it usually happens that no fields in the returned object super.clone

    need to be changed.
  • By convention, the returned object must be obtained by calling super.clone

    . If a class and all of it superclasses (except Object)

    obey this convention, it will be that x.clone().getClass() == x.getClass()

    .

So the code below 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();
    }

}

      

Links:

0


source


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

Ok, since the method clone

is a protected method in the class Object

, so it is available in your superclass UnChangeableBaseClass

as well, since it is propagated from the class Object

. This way you can access the method clone

using super.clone()

, from your base class DerivedLocalClass

.

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

I would suggest that even if you have the option to use a method clone

to clone an object, you shouldn't use it. It would be better to use in a derived class and add the call to the constructor of the base class. copy-constructor

super()

Also see Effective Java - Item#11 - Override clone judiciously

that suggest the method was clone

broken.



In this article: Josh Bloch on Design - Copy Constructor versus Cloning

you would like to see the first paragraph Bloch

: -

If you read the article on cloning in my book, especially if you read between the lines, you will know that I think the clone is deeply broken. There are several design flaws, the biggest of which is that the Cloned Interface has no cloning method. And that means it just doesn't work: doing something cloned doesn't say anything about what you can do about it. Instead, he says something about what he can do internally. It says that if you call super.clone repeatedly it ends up calling the object cloning method, that method will return a copy of the original field.

So the conclusion is that you can have copy constructor

in your DerivedLocalClass

, which will return you a copy of the caller, something like this: -

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

      

+2


source


JVM Cloning works using the Marker Cloneable interface rather than looking for Object.clone (). It is true that all Java classes inherit the clone method, but according to the 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 cannot do super.clone () because it is not marked as Cloneable. If you can't change the parent class, you'll have to make a copy yourself.

+1


source


I am using java 1.7 and I am not getting any problem running the code given by the OP. If the superclass does not have an overridden clone to throw the exception, I think this should work even if the superclass does not declare itself to be cloned.

Note that

public Object clone()

      

does not override clone method, it lacks a throws clause.

+1


source







All Articles