Hullo all,
想知道是否有任何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 =
编辑:哇,真的很快回复。多谢你们!所以我似乎无法使用这种方法向下转换...有没有其他方法可以在Java中进行向下转换?我确实考虑过让每个ChildN
类覆盖copy()
,但并不热衷于添加额外的样板代码。
答案 0 :(得分:9)
就像试图这样做:
public Object copy(){
return new Object();
}
然后尝试:
String s = ( String ) copy();
您的 Parent 类和 ChildN 类与 Object 和 String
具有相同的关系要使其正常工作,您需要执行以下操作:
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”方法。这是Prototype设计模式。
但是,使用此实现,您应该知道两个已检查的异常。这是完整的程序,可以毫无问题地编译和运行。
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 );
}
}
答案 1 :(得分:6)
演员有效地试图这样做:
ChildN copy = (ChildN) orig.copy();
(它正在计算执行时执行的强制转换,但这是因为orig.getClass()
将是ChildN.class
)但是,orig.copy()
不会返回ChildN的实例,它只返回Parent
的实例,因此无法转换为ChildN
。
答案 2 :(得分:4)
如果ChildN没有覆盖copy()以返回ChildN的实例,那么您正在尝试向下转换父类型的对象以键入ChildN
答案 3 :(得分:2)
java.lang.Class #cast(Object)如果Class#isInstance()返回false,则抛出ClassCastException。从该方法的javadoc:
确定指定的Object是否为 赋值与对象兼容 由本课程代表。这种方法 是Java的动态等价物 语言instanceof运算符... 具体来说,如果这样
Class
对象代表一个 声明类,此方法返回 如果指定true
Object
参数是一个 代表类的实例(或 任何子类);它返回 否则false
。
由于Parent不是子类的子类,因此isInstance()返回false,因此cast()会抛出异常。这可能违反了最不惊讶的原则,但它按照记录的方式工作 - cast()只能翻转,而不是垂头丧气。
答案 4 :(得分:2)
可能只是想要对象的复制/克隆。
在这种情况下,实现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方式执行的操作。
(是的,你也可以做一些花哨的内省游戏,但是只要你没有公共默认构造函数,这些方法就会失败或变得丑陋。无论你使用什么构造函数,克隆都可以工作。)
答案 5 :(得分:1)
(无法在评论中添加代码,因此我将在此处添加)
关于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区。]
答案 6 :(得分:0)
向下转换不起作用的原因是,当您将父对象转换为子类型时,您无法在父对象上调用子类型的方法。但它的另一种方式是......