8.5.2 向下转型与运行类型异常

由于向下转型(在继承层次中向上移动)会丢失聚类的类型信息,所以我们就想,通过向下转型-也就是在继承层次中向下移动-应该能够获取类型信息。然而,我们知道向上转型是安全的,因为基类不会具有大于导出类的接口。因此,我们通过基类接口发送的消息保证都能被接受。但是对于向下转型,例如,我们无法知道一个“几何形状”它确实就是一个“圆”,它可以是一个三角形、正方形或其他一些类型。

要解决这个问题,必须有某种方法来确保向下转型的正确性,使我们不至于贸易转型到一种错误类型,进而发出该对象无法接受的消息。这样做事极其不安全的。

在某些程序设计语言(如C++)中,我们必须执行一个特殊的操作来获得安全的向下转型。但是在Java语言中,所有转型都会得到检查!所以即使我们只是进行一次普通的加括弧形式的类型转换,在进入运行期时仍然会对其进行检查,以便保证它的确是我们希望的那种类型。如果不是,就会返回一个ClassCastException(类转型异常)。这种在运行期间对类型进行检查的行为称作“运行时类型识别”(RTTI)。下面的例子说明RTTI的行为:
//: polymorphism/RTTI.java
// Downcasting & Runtime type information(RTTI).
// {ThrowsException}

class Useful {
    public void f() {}
    public void g() {}
}

class MoreUseful extends Useful {
    public void f() {}
    public void g() {}
    public void u() {}
    public void v() {}
    public void w() {}
}

public class RTTI {
    public static void main(String[] args) {
        Useful[] x = {
            new Useful(),
            new MoreUseful()
        };
        x[0].f();
        x[1].g();
        // Compile time: method not found in Useful:
        //! x[1].u();
        ((MoreUseful)x[1]).u(); // Downcast /RTTI
        ((MoreUseful)x[0]).u(); // Exception thrown
    }
} ///:~
                

正如前一个示意图中所示,MoreUseful(更有用的)接口扩展了Useful(有用的)接口;但是由于它是继承而来的,所以它也可以向上转型到Useful类型。我们在main()方法中对数组x进行初始化时可以看到这种情况的发生。既然数组中的两个对象都属于Useful类,所以我们可以调用f()和g()这两个方法。如果我们试图调用u()方法(它只存在于MoreUseful),就会返回一条编译时出错消息。

如果想访问MoreUseful对象的扩展接口,就可以尝试进行向下转型。如果所转类型是正确的类型,那么转型成功;否则,就会返回一个ClassCastException异常。

猜你喜欢

转载自www.cnblogs.com/cgy-home/p/11141456.html