sHA*_*ILU 3 java inheritance casting type-conversion downcast
请检查以下程序.
我怀疑编译器何时会在编译器级别发出转换异常,何时它会在runtime?
喜欢下面的程序,表达
我认为(Redwood) new Tree()应该在编译时失败,因为Tree不是Redwood.但它没有失败compile time,正如预期的那样失败runtime!!!
public class Redwood extends Tree {
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;
}
}
class Tree { }
Run Code Online (Sandbox Code Playgroud)
Tree不一定是Redwood,但它可能是,因此缺少编译时错误.
在这种情况下,很明显它不是,但编译器倾向于抱怨绝对不正确的事情,而不是可能或可能不正确.在这种情况下逻辑是不正确的,而不是代码本身,逻辑是你的问题,而不是编译器.
Tree t = new Redwood();
Redwood r = (Redwood) t;
Run Code Online (Sandbox Code Playgroud)
在编译和运行时都完美有效.
我在解释中又添加了一个子类。
Tree
/ \
/ \
/ \
Redwood Blackwood
Run Code Online (Sandbox Code Playgroud)
在这个层次结构中:
Upcast:当我们沿类层次结构向一个方向投射引用时from the sub classes towards the root。我们需要的不是在这种情况下使用转换运算符
大写示例:
ARedwood或Blackwood两者都是tree:所以
Tree t1;
Tree t2;
Redwood r = new Redwood() ;
Blackwood b = new Blackwood() ;
t1 = r; // Valid
t2 = b; // Valid
Run Code Online (Sandbox Code Playgroud)
向下转换:当我们沿类层次结构向一个方向投射引用时from the root class towards the children or subclasses。我们需要明确的类型转换。
垂头丧气的例子:
Redwood r = new Tree(); //compiler error, because Tree is not a Redwood
Blackwood r = new Tree(); //compiler error, because Tree is not a Blackwood
Run Code Online (Sandbox Code Playgroud)
Tree object 如果它确实指向 Redwood或Blackwook对象,则需要显式键入 cast a ,否则它会在运行时出错。例如
在这种情况下:
Tree t1;
Tree t2;
Redwood r = new Redwood() ;
Blackwood b = new Blackwood() ;
t1 = r; // Valid
t2 = r; // Valid
Redwood r2 = (Redwood)t1;
Blackwood b2 = (Blackwood)t2
Run Code Online (Sandbox Code Playgroud)
[回答]
Redwood r = (Redwood) new Tree(); 为什么没有编译器错误?
它的Downcast示例:
源Redwood r = (Redwood) new Tree();拳头创建 Tree 对象并类型转换为Redwood.
你可以这样想:
Tree t = new Tree();`
Redwood r = (Redwood)t;
Run Code Online (Sandbox Code Playgroud)
所以它在编译时没问题,
[回答]
为什么运行时错误?
但实际上Redwood子类不能指向Tree超类对象。所以你的代码在运行时失败。
树 t = 新树();
t指向Tree()对象不是Redwood()。这就是运行时错误的原因。
编译器现在不知道什么是有价值的,t并且在语法上每件事都是写的。但是在运行时由于Redwood r = (Redwood)t;,ift的对象在哪里Tree class出错了。
[建议:]
我建议您使用instanceof运算符:
强制转换/强制操作用于类型之间的转换,instanceof操作符用于在运行时检查类型信息。*
说明:
该的instanceof运算符可以让你决定一个对象的类型。它接受运算符左侧的对象和运算符右侧的类型,并返回一个布尔值,指示该对象是否属于该类型。用一个例子最清楚地证明了这一点:
if (t instanceof Redwood)
{
Redwood r = (Redwood)t;
// rest of your code
}
Run Code Online (Sandbox Code Playgroud)
但我还要补充一点:从基类型转换为派生类型是一件坏事。 参考:注意 instanceof 运算符
编译器只会查看表达式的编译时类型。它不对表达式的运行时类型进行假设。new Tree()具有编译时类型Tree,因此(Redwood)new Tree()与(Redwood)myTreeVariable.