How do i convince the compiler an Object is cloneable (java)?
Asked Answered
C

5

7

i want to clone a given object.

if i do this

public class Something{
    Object o; //set in the constructor
    public Something(Object o){
         this.o = o;}
    public Something clone() throws CloneNotSupportedException{
         Something temp = super.clone();
         if (o instanceof Cloneable) //important part
             temp.o = o.clone(); //important part
         else temp.o = o;
    }
}

this will not work becuase o.clone() is protected.

if i do this instead

         if (o instanceof Cloneable) //important part
             temp.o = ((Cloneable)o).clone(); //important part

it won't work either because Cloneable is an empty interface.

so how do i convince the compiler that you can clone o?

Colous answered 21/6, 2015 at 11:49 Comment(8)
@immibis, I don't think your comment adds much value to be honest.Orchid
You must make your class implement Cloneable and implement the clone method.Gehlbach
From doc: "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."Gehlbach
Also, see this: #1139269Orchid
docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.htmlGehlbach
@Orchid Sure it does. It adds the knowledge that: you can't.Blackdamp
@immibis so it is actually impossible if clone has not been overriden?Gehlbach
@RishavKundu It's impossible to do sanely... but reflection allows you to do insane things, so you could try using that.Blackdamp
E
2

You can't, when implementing clone() one must know what is cloning, must know the implementation class.

An alternative to cloning is to use copy-constructor, that has the same issue, you must know the class.

Some say do not use clone, others say define your own interface, eg: Copyable http://c2.com/cgi/wiki?CloneableDoesNotImplementClone

Exactitude answered 21/6, 2015 at 12:4 Comment(0)
B
2

Alternative would be to use serialization if it's possible to implement Serializable interface. Downside is the performance ofcourse.

https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/SerializationUtils.html#clone(java.io.Serializable)

If you don't want to use apache commons you could do the same thing using ObjectOutputStream/ObjectInputStream.

Booze answered 21/6, 2015 at 12:10 Comment(0)
S
1

You can do it with reflection

//We need reflection
import java.lang.reflect.*;
    //This class is the backbone of the feature
    public class MyCloneable implements Cloneable {

        //A constructor. For the sake of simplicity, the constructor is an empty constructor.
        public MyCloneable() {}

        //We implement the clone method. This returns a clone
        protected Object clone() throws CloneNotSupportedException {
            //We need the class of the object
            class c = this.getClass();
            //We get the empty constructor of the object
            Constructor constructor = c.getConstructor(new Class[]{});
            //newClone will be the cloned object
            Object newClone = constructor.newInstance(new Object[]{});
            //We get the array of fields
            Field[] fields = c.getDeclaredFields();
            //We iterate the fields to copy them. You might want to close these too, but for the sake of simplicity I did not tackle with this issue
            for (int fieldIndex = 0; fieldIndex < fields.length; fieldIndex++) {
                //We copy the field values of this into the clone
                fields[fieldIndex].set(newClone, fields[fieldIndex].get(this));
            }
            //newClone is ready and kicking
            return newClone;
        }

        //We need this method to be able to reach the clone method publicly
        public Object runClone() throws CloneNotSupportedException {
            return this.clone();
        }

    }

This code is untested, any observation is welcome.

You need to use objects of classes which are inherited from MyCloneable.

Sides answered 21/6, 2015 at 12:31 Comment(0)
I
0

There is no general way to clone an object in Java. The type must provide a method to clone (which may be called clone() or something else; doesn't matter) in its public API, and there is no common supertype for such types in Java.

Inceptive answered 23/6, 2015 at 1:24 Comment(0)
A
-1

The java.lang.Cloneable interface must be implemented by the class whose object clone we want to create. If we don't implement Cloneable interface, clone() method generates CloneNotSupportedException.

The clone() method is defined in the Object class. Syntax of the clone() method is as follows:

protected Object clone() throws CloneNotSupportedException

So your class should be as

public class Something implements Cloneable {

    private Object o; //set in the constructor

    public Something(Object o) {
        this.o = o;
    }

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

    public Object getObject() {
        return o;
    }

    public static void main(String[] args) {
        Something s = new Something("try");
        System.out.println(s.getObject());
        try {
            Something s2 = (Something) s.clone();
            System.out.println(s2.getObject());
        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(Something.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
Archespore answered 21/6, 2015 at 12:13 Comment(1)
The question was how to clone o.Blackdamp

© 2022 - 2024 — McMap. All rights reserved.