Java 中的“动态”转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/401415/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Dynamic" Casting in Java
提问by user50264
Hullo all,
大家好,
Wondering if there are any Java hackers who can clue me in at to why the following doesn't work:
想知道是否有任何 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());
}
}
The code is quite happy to compile, but decides to throw a ClassCastException at runtime D=
代码很高兴编译,但决定在运行时抛出 ClassCastException D=
Edit:Whoah, really quick replies. Thanks guys! So it seems I cannot downcast using this method... is there any other way to do downcasting in Java? I did think about having each ChildNclass overwrite copy(), but wasn't enthusiastic about adding the extra boilerplate code.
编辑:哇,回复真快。多谢你们!所以似乎我不能使用这种方法进行向下转换……还有其他方法可以在 Java 中进行向下转换吗?我确实考虑过让每个ChildN类都覆盖copy(),但并不热衷于添加额外的样板代码。
采纳答案by Scott Stanchfield
(Can't add code in a comment, so I'll add here)
(不能在评论中添加代码,所以我会在这里添加)
Regarding Cloneable: if you're implementing Cloneable, implement it as follows; much cleaner to call...
关于 Cloneable:如果您正在实施 Cloneable,请按如下方式实施;更干净的电话...
public class Foo implements Cloneable {
public Foo clone() {
try {
return (Foo) super.clone();
} catch (CloneNotSupportedException e) {
return null; // can never happen!
}
}
[EDIT: I've also seen other folks use
[编辑:我也看到其他人使用
throw new AssertionError("This should never happen! I'm Cloneable!");
in the catch block.]
在 catch 块中。]
回答by OscarRyz
Is like trying to do this:
就像尝试这样做:
public Object copy(){
return new Object();
}
And then attempt to:
然后尝试:
String s = ( String ) copy();
Your Parentclass and ChildNclass have the same relationship as Objectand String
您的Parent类和ChildN类与Object和String具有相同的关系
To make it work you would need to do the following:
要使其工作,您需要执行以下操作:
public class ChildN extends Parent {
public Parent copy() {
return new ChildN();
}
}
That is, override the "copy" method and return the right instance.
也就是说,覆盖“复制”方法并返回正确的实例。
EDIT编辑
As per your edit. That is actually possible. This could be one possible way:
根据您的编辑。这实际上是可能的。这可能是一种可能的方式:
public class Parent {
public Parent copy() {
Parent copy = this.getClass().newInstance();
//...
return copy;
}
}
That way you don't have to override the "copy" method in each subclass. This is the Prototype design pattern.
这样你就不必覆盖每个子类中的“复制”方法。这就是原型设计模式。
However using this implementation you should be aware two checked exceptions. Here's the complete program that compiles and runs without problems.
但是使用这个实现你应该知道两个检查异常。这是编译和运行没有问题的完整程序。
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 );
}
}
回答by Jon Skeet
The cast is effectively trying to do this:
演员阵容正在有效地尝试这样做:
ChildN copy = (ChildN) orig.copy();
(It's working out the cast to perform at execution time, but that's what it will be because orig.getClass()will be ChildN.class) However, orig.copy()doesn't return an instance of ChildN, it returns an instance of just Parent, so it can't be cast to ChildN.
(它正在计算要在执行时执行的强制转换,但这就是它的结果,因为orig.getClass()will ChildN.class)但是,orig.copy()它不返回 ChildN 的实例,而是返回 just 的实例Parent,因此不能将其强制转换为ChildN。
回答by erikkallen
If ChildN does not override copy() to return an instance of ChildN, then you are trying to downcast an object of type parent to type ChildN
如果 ChildN 没有覆盖 copy() 以返回 ChildN 的实例,那么您正在尝试将 parent 类型的对象向下转换为 ChildN 类型
回答by sk.
java.lang.Class#cast(Object) throws a ClassCastException if Class#isInstance() returns false. From the javadoc for that method:
如果 Class#isInstance() 返回 false,则 java.lang.Class#cast(Object) 会抛出 ClassCastException。从该方法的javadoc:
Determines if the specified Object is assignment-compatible with the object represented by this Class. This method is the dynamic equivalent of the Java language instanceof operator... Specifically, if this
Classobject represents a declared class, this method returnstrueif the specifiedObjectargument is an instance of the represented class (or of any of its subclasses); it returnsfalseotherwise.
确定指定的 Object 是否与由此类表示的对象赋值兼容。此方法是 Java 语言 instanceof 运算符的动态等价物... 具体而言,如果此
Class对象表示已声明的类,则此方法返回,true如果指定的Object参数是所表示的类(或其任何子类)的实例;否则返回false。
Since Parent is not a subclass of child, isInstance() returns false so cast() throws the exception. This may violate the principle of least astonishment but it's working the way it's documented - cast() can only upcast, not downcast.
由于 Parent 不是 child 的子类,isInstance() 返回 false,因此 cast() 抛出异常。这可能违反了最少惊讶的原则,但它按照记录的方式工作 - cast() 只能向上转换,不能向下转换。
回答by Thomas Morgner
Could it be that you simply want a copy/clone of your object.
可能是您只是想要对象的副本/克隆。
In that case, implement the Cloneable interface and override clone() as necessary.
在这种情况下,实现 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());
}
}
This does exactly what your "copy()" method tried to do in the Java way.
这正是您的“copy()”方法试图以 Java 方式执行的操作。
(Yes, you could do fancy introspection games too, but those methods fail or become ugly as soon as you do not have a public default-constructor. Clone works in any case no matter what constructors you have.)
(是的,你也可以做花哨的自省游戏,但是一旦你没有公共默认构造函数,这些方法就会失败或变得丑陋。无论你有什么构造函数,克隆在任何情况下都可以工作。)
回答by Sathish
The reason downcasting doesnt work is because, when you cast a parent object to a child type, theres no way you can invoke child type's methods on the parent object. But it works the other way...
向下转换不起作用的原因是,当您将父对象转换为子类型时,您无法在父对象上调用子类型的方法。但它以另一种方式工作......

