[英]Java Class Casting Rules
public static void main(String[] args) {
new Redwood().go();
}
void go() {
go2(new Tree(), new Redwood());
go2((Redwood) new Tree(), new Redwood());
}
void go2(Tree t1, Redwood r1) {
Redwood r2 = (Redwood)t1;
Tree t2 = (Tree)r1;
}
}
Given the class Redwood extends Tree, the main() method is in Redwood and Tree is an empty class with only a default constructor; 给定Redwood扩展Tree类,则main()方法位于Redwood中,并且Tree是一个空类,仅具有默认构造函数; the answer to this exam question is "A ClassCastException will be thrown when the code attempts to downcast a Tree to a Redwood." 该考试问题的答案是“当代码尝试将Tree转换为Redwood时,将引发ClassCastException。”
I want to know why the exception is thrown and where. 我想知道为什么会引发异常以及在何处。 From my understanding you can declare Tree t1 = new Redwood() so why can't I cast a Tree to a Redwood directly? 根据我的理解,您可以声明Tree t1 = new Redwood(),为什么我不能直接将Tree投射到Redwood?
By using a cast you're essentially telling the compiler "trust me. I'm a professional, I know what I'm doing and I know that although you can't guarantee it, I'm telling you that this tree variable is definitely going to be a redwood." 通过使用强制转换,您实际上是在告诉编译器“相信我。我是专业人士,我知道我在做什么,我知道尽管不能保证,但是我告诉你这个树变量是肯定会成为红杉。”
Since the tree isn't actually a redwood(it's an tree, you could do Tree tree = new Redwood(); and it'd be a redwood) the VM throws an exception at runtime because you've violated that trust (you told the compiler everything would be ok and it's not!) 由于树实际上不是一棵红杉(它是一棵树,您可以执行Tree tree = new Redwood();它将是一棵红杉),因为您违反了这种信任,VM在运行时抛出异常(您告诉编译器一切都会好起来的,不是!)
The compiler is a bit smarter than just blindly accepting everything, if you try and cast objects in different inheritence hierarchies (cast a redwood to a String for example) then the compiler will throw it back at you because it knows that could never possibly work. 编译器比盲目地接受所有内容要聪明一些,如果您尝试将对象强制转换为不同的继承层次结构(例如,将红木投射到String中),则编译器会将其扔给您,因为它知道这种方法永远无法工作。
Because you're essentially just stopping the compiler from complaining, every time you cast it's important to check that you won't cause a ClassCastException by using instanceof in an if statement (or something to that effect.) 因为您实际上只是在停止编译器的抱怨,所以每次转换时,都必须在if语句中使用instanceof(或有此作用的东西)来检查是否不会导致ClassCastException。
take reference http://www.xyzws.com/Javafaq/why-down-casting-throws-classcastexception/125 请参考http://www.xyzws.com/Javafaq/why-down-casting-throws-classcastexception/125
Every Redwood
is a Tree
. 每个Redwood
都是一Tree
。 This is why Tree t2 = (Tree) r1;
这就是为什么Tree t2 = (Tree) r1;
works. 作品。
Not every Tree
is a Redwood
. 并非每Tree
都是Redwood
。 This is why Redwood r2 = (Redwood) t1;
这就是为什么Redwood r2 = (Redwood) t1;
will not work if t1
is a Tree
but not Redwood
. 如果t1
是Tree
但不是Redwood
将不起作用。
More formally, see JLS §5.1.6 : 更正式地,请参见JLS§5.1.6 :
Six kinds of conversions are called the narrowing reference conversions: 六种转换称为收窄参考转换:
From any reference type S to any reference type T, provided that S is a proper supertype of T (§4.10). 从任何引用类型S到任何引用类型T,前提是S是T的适当超类型(第4.10节)。
An important special case is that there is a narrowing reference conversion from the class type Object to any other reference type (§4.12.4). 一个重要的特殊情况是,从类类型Object到任何其他引用类型的引用转换范围越来越窄(第4.12.4节)。
From any class type C to any non-parameterized interface type K, provided that C is not final and does not implement K. 从任何类类型C到任何非参数化接口类型K,只要C不是最终的并且不实现K。
From any interface type J to any non-parameterized class type C that is not final. 从任何接口类型J到非最终的任何非参数化类类型C。
From any interface type J to any non-parameterized interface type K, provided that J is not a subinterface of K. 如果J不是K的子接口,则从任何接口类型J到任何非参数化接口类型K。
From the interface types Cloneable and java.io.Serializable to any array type T[]. 从接口类型Cloneable和java.io.Serializable到任何数组类型T []。
From any array type SC[] to any array type TC[], provided that SC and TC are reference types and there is a narrowing reference conversion from SC to TC. 从任何数组类型SC []到任何数组类型TC [],条件是SC和TC是引用类型,并且从SC到TC的引用转换范围越来越窄。
Such conversions require a test at run time to find out whether the actual reference value is a legitimate value of the new type. 此类转换需要在运行时进行测试,以查明实际参考值是否为新类型的合法值。 If not, then a ClassCastException is thrown. 如果不是,则抛出ClassCastException。
Simply because Every Redwood is a Tree but Every Tree is not Redwood. 仅仅是因为每棵红木都是一棵树,但每棵树都不是红木。 The Compiler is smart enough to protect your program to do wrong things. 编译器足够聪明,可以保护您的程序执行错误的操作。
A variable of type Tree
does not hold an object of type Tree
; 类型的变量Tree
不成立类型的对象Tree
; instead, it holds either null
or a reference to an object which is guaranteed to be usable as a Tree
object. 相反,它持有null
或对对象的引用 ,该对象保证可以用作Tree
对象。 Likewise with a variable of type Redwood
. 同样,类型为Redwood
的变量。
Because Redwood
inherits from Tree
, a Redwood
object is guaranteed to be usable as a Tree
object, and a variable of type Tree
might hold a reference to such an object. 因为Redwood
从Tree
继承,所以保证Redwood
对象可用作Tree
对象,并且Tree
类型的变量可能包含对该对象的引用。 If one tries to cast a variable of type Tree
to a variable of type Redwood
, such a cast will succeed if the variable holds null
[since a variable of type Redwood
can hold null
], or if the variable holds a reference to an object which is usable as a Redwood
[since a variable of that type can hold any such reference], but will fail if the variable holds a reference to an object which is not usable as a Redwood
[variables of type Redwood
cannot hold references to such objects]. 如果尝试将类型为Tree
的变量转换为Redwood
类型的变量,则如果该变量持有null
[因为Redwood
类型的变量可以持有null
],或者该变量持有对该对象的引用,则此类转换将成功可用作Redwood
[因为该类型的变量可以保存任何此类引用],但如果该变量持有对不可用作Redwood
的对象的引用,则将失败[ Redwood
类型的变量无法保存对此类对象的引用] 。
Note that if you try to cast the result of a new
expression, the system will behave as though that result was stored into a temporary variable, and the cast was applied to that. 请注意,如果您尝试强制转换new
表达式的结果,系统将表现为该结果已存储到临时变量中,并且强制转换已应用于该临时变量。 Whether or not there is any way the variable could actually hold a reference to an object which is usable as a Redwood
, the compiler may still behave as though the variable might or might not hold such a reference, and only discover that it doesn't when the code is executed. 不管变量是否有任何实际方式可以保存对可用作Redwood
的对象的引用,编译器仍可能会表现出该变量可能或可能不包含此类引用的行为,并且只会发现它没有代码执行时。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.