我有一个Person
类,它实现了Cloneable
。然后我有对象p
和o
引用Person
对象。我试图克隆一个到另一个,并发现以下工作:
Object p = new Person("Heather");
Object o = ((Person)p).clone();
(我必须使用该广播代码,因为clone()
在对象中受到保护。我使用此代码来调用clone()
中的Person
。)
我需要知道的是如何使用Class.cast()
执行上述演员表。我知道如何施放一次,它会是这样的:
Object o = p.getClass().cast(p);
但是我如何以这种方式进行嵌套的转换示例。 (我需要知道,因为在这个项目中,我不会总是知道要转换为什么类,但我知道该类是Cloneable
。)
我试过...... ((Cloneable的)P).clone() ......但这不起作用。 clone()方法是Object类中的受保护方法,而Cloneable接口没有clone()方法,因此编译器无法识别它。
我一直在找一个答案而在任何地方都找不到。谢谢你的帮助。
答案 0 :(得分:1)
在代码中使用clone()
是不常见的(我从未使用过它,也没有看到它像那样明确地使用过)。
用于制作副本的常用模式是copy constructor,例如:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
// Copy constructor
public Person(Person person) {
this(person.name);
}
}
源对象的重要字段的值用于初始化新对象的字段值。
答案 1 :(得分:0)
由于克隆的工作方式,这是一件困难的事情。正如您所注意到的,几乎克隆是受保护的方法,因此您需要在编译时使用类来调用它。有一种方法可以声明一个为其分配公共访问权限的接口:
public interface PublicCloneable
extends Cloneable {
public Object clone();
}
然后实现它而不是Cloneable。然后你就可以转换为PublicCloneable来调用clone。这样可以正常工作,但它仍然带有克隆的所有常见问题。
创建复制构造函数是克隆的一个很好的替代方法,如果在编译时不知道类,可以使用反射调用它:
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
总是会返回Class<?>
,因此如果您不介意未经检查的演员,也可以将其设为通用。)
你在这里遇到的可能是你需要考虑你的设计。就个人而言,这听起来像一个通用工厂可能有利的情况。
基本上是这样的:
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;
}
你可以称之为
doStuffInvolvingCopy(new Person("Heather"), new PersonCopier());
或者可能将工厂注册在某处,这样就不需要传递它们了。
工厂很好,因为他们不使用克隆而不使用反射。