ran
ran

Reputation: 737

object cloning with out implementing cloneable interface

to clone the object do i need to implement 'cloneable' interface. because here my class is a jar file(i mean API). so i can't edit the class. i heard that all classes are extends the base object class and this object class implements cloneable interface. does that mean can we directly clone the object with out implementing the interface. if so in my eclipse i am not getting any option to clone the object. is there any other way to clone the object without implementing the cloneable interface. please explain.

Upvotes: 14

Views: 37473

Answers (9)

grigouille
grigouille

Reputation: 705

You can override the clone method without implementing Cloneable. Just call some copy constructor :

public class Foo {
    private final int a;

    private Foo(int a) {
        this.a = a;
    }

    @Override
    public Foo clone() {
        return new Foo(this.a);
    }
}

Note that this method doesn't call super.clone. You may read this article : Overriding Clone without calling the super.clone

Upvotes: 0

Julian Kreuzer
Julian Kreuzer

Reputation: 356

You could use Unsafe to create a instance of an object and than copy the values into the new instance by using java reflection. But like the name Unsafe says this is not a really good solution.

public static Unsafe unsafe;
static {
    Field f;
    try {
        f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        unsafe = (Unsafe) f.get(null);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }

}

public static <T> T clone(T object) throws InstantiationException {
    T instance = (T) unsafe.allocateInstance(object.getClass());
    copyInto(object,instance);
    return instance;
}

public static void copyInto(Object source,Object destination){
    Class<?> clazz = source.getClass();
    while (!clazz.equals(Object.class)) {
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            try {
                field.set(destination, field.get(source));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        clazz = clazz.getSuperclass();
    }
}

Upvotes: 0

SANN3
SANN3

Reputation: 10069

Their is a api which clone the object without implementing the cloneable interface.

Try this

https://github.com/kostaskougios/cloning

Also you can find more details about cloning objects here

http://javatechniques.com/blog/faster-deep-copies-of-java-objects/

Upvotes: 3

Prakash Gaikwad
Prakash Gaikwad

Reputation: 81

Using Reflection API you can achieve it

Upvotes: 1

sunil.tanwar
sunil.tanwar

Reputation: 81

It is not mandatory to implement cloneable interface to make a clone of a object. You can write your own clone method in the class whose object you want to clone.

Upvotes: 0

orien
orien

Reputation: 2200

The Java Object class does not implements the Cloneable interface. It does however have the clone() method. But this method is protected and will throw CloneNotSupportedException if called on an object that does not implement the Cloneable interface. So if you cannot modify the class you want to clone you're out of luck and will have to find another way to copy the instance.

It should be note however that the clone system in Java is full of holes and generally not used anymore. Check out this interview with Josh Bloch from 2002 explaining a few of the issues.

Upvotes: 7

kylewm
kylewm

Reputation: 634

It's usually best practice to avoid clone() anyway because it's difficult to do correctly (http://www.javapractices.com/topic/TopicAction.do?Id=71). Perhaps the class in question has a copy constructor?

Alternatively if it implements Serializable or Externalizable, you can deep copy it by writing it to a byte stream and reading it back in

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Object deepCopy = ois.readObject();

(from http://www.jguru.com/faq/view.jsp?EID=20435). This is quick and easy but not pretty... I would generally consider it a last resort.

Upvotes: 9

mprabhat
mprabhat

Reputation: 20323

The clone() method in Object class is protected which means all classes will inherit it with protected access modifier, hence if you try to access it outside that class without cloning it you wont see it, also it will throw you CloneNotSupportedException if you try to invoke it without implementing Cloneable interface.

In case you are looking at having a way create a behaviour of clone you need to write a new method in your class and then you create a copy of all the fields in that, its basically like create a new copy of an existing state of an object.

public class TestCloneable {
private String name = null;

/**
 * @param name the name to set
 */
public void setName(String name) {
    this.name = name;
}

/**
 * @return the name
 */
public String getName() {
    return name;
}


public TestCloneable createCopy(){
    TestCloneable testCloneable = new TestCloneable();
    testCloneable.setName(this.getName());
    return testCloneable;
}

}

Upvotes: 0

Gaurav Saxena
Gaurav Saxena

Reputation: 4297

Trying to invoke clone method on a class which doesn't implements Cloneable throws CloneNotSupported Exception and no Object class doesn't implement Cloneable.

here is the javadoc from the clone method of Object class

CloneNotSupportedException  if the object's class does not
 *               support the <code>Cloneable</code> interface. Subclasses
 *               that override the <code>clone</code> method can also
 *               throw this exception to indicate that an instance cannot
 *               be cloned.

Also Object#clone method is protected so you need to implement the clone method in your class and make it public so it can be accessible to classes making objects of your class which can then invoke clone. A good example is the way clone is implement in ArrayList

ArrayList implements cloneable like below public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable

and then implements the clone method:

/**
 * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
 * elements themselves are not copied.)
 *
 * @return a clone of this <tt>ArrayList</tt> instance
 */
public Object clone() {
try {
    ArrayList<E> v = (ArrayList<E>) super.clone();
    v.elementData = Arrays.copyOf(elementData, size);
    v.modCount = 0;
    return v;
} catch (CloneNotSupportedException e) {
    // this shouldn't happen, since we are Cloneable
    throw new InternalError();
}
}

Upvotes: 0

Related Questions