编译时和运行时的Downcasting/Upcasting错误?

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)

Mik*_*ike 5

Tree不一定是Redwood,但它可能是,因此缺少编译时错误.

在这种情况下,很明显它不是,但编译器倾向于抱怨绝对不正确的事情,而不是可能或可能不正确.在这种情况下逻辑是不正确的,而不是代码本身,逻辑是你的问题,而不是编译器.

Tree t = new Redwood();
Redwood r = (Redwood) t;
Run Code Online (Sandbox Code Playgroud)

在编译和运行时都完美有效.

  • `new Tree()`返回对Tree的引用.你永远不会有Java中的对象.仅引用对象. (4认同)

Gri*_*han 5

我在解释中又添加了一个子类。

       Tree
      /    \
     /      \
    /        \ 
Redwood       Blackwood  
Run Code Online (Sandbox Code Playgroud)

在这个层次结构中:

Upcast:当我们沿类层次结构向一个方向投射引用时from the sub classes towards the root我们需要的不是在这种情况下使用转换运算符

大写示例:

ARedwoodBlackwood两者都是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 如果它确实指向 RedwoodBlackwook对象,需要显式键入 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 运算符


ign*_*nis 5

编译器只会查看表达式的编译时类型。它不对表达式的运行时类型进行假设。new Tree()具有编译时类型Tree,因此(Redwood)new Tree()(Redwood)myTreeVariable.