“动态”铸造
喂所有,“动态”铸造
想知道是否有任何Java黑客谁可以给我介绍的,为什么下面不工作:
public class Parent {
public Parent copy() {
Parent aCopy = new Parent();
...
return aCopy;
}
}
public class ChildN extends Parent {
...
}
public class Driver {
public static void main(String[] args) {
ChildN orig = new ChildN();
...
ChildN copy = orig.getClass().cast(orig.copy());
}
}
的代码非常开心编译,但决定在运行时抛出一个ClassCastException D =
编辑:哇,真的很快回复。多谢你们!所以看起来我不能使用这种方法downcast ...是否有任何其他方式在Java中进行向下转换?我确实想过让每个ChildN
课程都覆盖copy()
,但并不热衷于添加额外的样板代码。
(无法在评论中添加代码,所以我要在此添加)
关于Cloneable:如果您要实现Cloneable,请按如下方式实施:更清洁打电话......
public class Foo implements Cloneable {
public Foo clone() {
try {
return (Foo) super.clone();
} catch (CloneNotSupportedException e) {
return null; // can never happen!
}
}
[编辑:我也看到其他人使用
throw new AssertionError("This should never happen! I'm Cloneable!");
在catch块
]
演员被有效试图做到这一点:
ChildN copy = (ChildN) orig.copy();
(它的工作了剧组在执行时进行,但是这将是什么,因为orig.getClass()
会ChildN.class
)但是,orig.copy()
不返回一个ChildN的实例,它返回的只是Parent
的一个实例,所以它不能被转换为ChildN
。
如果ChildN没有覆盖副本()返回ChildN的实例,那么你想垂头丧气型亲本的目的是键入ChildN
就像是试图做到这一点:
public Object copy(){
return new Object();
}
然后尝试:
String s = (String) copy();
你家长类和ChildN级有作为对象和字符串的关系一样
为了使它工作,你需要做到以下几点:
public class ChildN extends Parent {
public Parent copy() {
return new ChildN();
}
}
也就是说,覆盖“复制”的方法,并返回正确的实例。
编辑
根据您的编辑。这实际上是可能的。这可能是一种可能的方法:
public class Parent {
public Parent copy() {
Parent copy = this.getClass().newInstance();
//...
return copy;
}
}
这样你就不必在每个子类中重写“copy”方法。这是原型设计模式。
但是使用这个实现你应该知道两个检查的异常。这是编译和运行没有问题的完整程序。
public class Parent {
public Parent copy() throws InstantiationException, IllegalAccessException {
Parent copy = this.getClass().newInstance();
//...
return copy;
}
}
class ChildN extends Parent {}
class Driver {
public static void main(String[] args) throws InstantiationException , IllegalAccessException {
ChildN orig = new ChildN();
ChildN copy = orig.getClass().cast(orig.copy());
System.out.println("Greetings from : " + copy);
}
}
以身作则!这个答案对我来说很清楚。现在可以声明Child.copy来返回一个ChildN iso一个Parent吗? (我知道它可以在C++中) – xtofl 2008-12-30 21:00:25
不在Java中。至少不在Java源代码中。若要将问题稍微混淆,可以在Java字节码中允许* – 2008-12-30 21:18:21
Java 5+中的源代码允许使用它。 – 2008-12-30 21:35:30
java.lang.Class#cast(Object)如果Class#isInstance()返回false,则抛出ClassCastException。根据JavaDoc该方法:
确定指定对象是与该Class表示的对象 赋值兼容。此方法 是Java语言 instanceof操作的动态等效... 具体地,如果此
Class
对象表示 声明的类,该方法返回true
如果指定Object
参数是表示类的一个实例 (或其任何子类的 );否则返回false
。
因为Parent不是子类的子类,所以isInstance()返回false,所以cast()抛出异常。这可能会违反最不惊人的原则,但它按照记录的方式工作 - cast()只能向上播放,而不能向下播放。
难道你只是想要你的对象的复制/克隆。
在这种情况下,请根据需要实现Cloneable接口并覆盖clone()。
public class Parent implement Cloneable {
public Object clone() throws CloneNotSupportedException {
Parent aCopy = (Parent) super.clone();
...
return aCopy;
}
}
public class ChildN extends Parent {
...
}
public class Driver {
public static void main(String[] args) {
ChildN orig = new ChildN();
...
ChildN copy = orig.getClass().cast(orig.clone());
}
}
这正是您的“copy()”方法尝试以Java方式执行的操作。
(是的,你可以做花哨的反省游戏太多,但这些方法失败或很快变得丑陋,你没有一个公共默认构造函数。克隆可以在任何情况下,无论是什么构造你。)
之所以向下转换不工作是因为,当您将父对象转换为子类型时,您无法在父对象上调用子类型的方法。但它以另一种方式工作...
你可以做到这一点。看看我的编辑。我虽然在第一时间理解“铸造”有困难。 – OscarRyz 2008-12-30 22:06:31