Reputation: 179
I have a Person
class, which implements Cloneable
. I then have Objects p
and o
which reference a Person
object. I am trying to clone one into another, and discovered that the following works:
Object p = new Person("Heather");
Object o = ((Person)p).clone();
(I have to use that cast because clone()
is protected in Object. I use this to call clone()
in Person
instead.)
What I need to know is how to perform the above cast using Class.cast()
. I know how to cast once, it would be something like this:
Object o = p.getClass().cast(p);
But how do I do the nested casting example in this way. (I need to know because in this project, I won't always know what class to cast to but I WILL know the class is Cloneable
.)
I tried… ((Cloneable)p).clone() ...but that doesn't work. The clone() method is a protected method in the Object class, and interface Cloneable does not have a clone() method, so the compiler can't recognize it.
I've looked all over for an answer and can't find one anywhere. Thank you for your help.
Upvotes: 1
Views: 874
Reputation: 37845
This is kind of a difficult thing because of the way clone works. As you noticed, pretty much clone is a protected method so you need a class at compile time to call it. There's one way around this which is to declare an interface that assigns it public access:
public interface PublicCloneable
extends Cloneable {
public Object clone();
}
Then implement that instead of Cloneable. Then you are able to cast to PublicCloneable to call clone. This will work OK but it still carries with it all the normal problems with clone.
Creating a copy constructor is a great alternative to clone and you can make a method to call it with reflection if you don't know the class at compile time:
static Object reflectionCopy(Object obj) {
try {
Class<?> cls = obj.getClass();
Constructor<?> ctor = cls.getConstructor(cls);
return ctor.newInstance(obj);
} catch(Exception e) {
return obj;
}
}
(getClass
always returns a Class<?>
so that can also be made generic if you don't mind an unchecked cast.)
Probably what you are running in to here is an indication you need to think about your design. Personally this sounds to me like a case where a generic factory could be advantageous.
Basically something like this:
public interface Copier<T> {
public T createCopy(T obj);
}
public class PersonCopier
implements Copier<Person> {
@Override
public Person createCopy(Person person) {
return new Person(person.getName());
}
}
public static <T> T doStuffInvolvingCopy(T inObject, Copier<T> copier) {
...
T copy = copier.createCopy(inObject);
...
return copy;
}
You might call that like
doStuffInvolvingCopy(new Person("Heather"), new PersonCopier());
or perhaps keep the factories registered somewhere so they do not need to be passed around.
Factories are good because they don't use clone and don't use reflection.
Upvotes: 0
Reputation: 424993
Using clone()
is unusual in code (I have never used it nor seen it used explicitly like that).
The usual pattern to use for making copies is the copy constructor, eg:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
// Copy constructor
public Person(Person person) {
this(person.name);
}
}
Values of the important fields of the source object are used to initialize field values of the new object.
Upvotes: 1