由于我们在上溯造型(在担任布局中向上移动)期间丢失了详细的范例信息,所觉得了获取详细的范例信息——亦即在分级布局中向下移动——我们必需利用 “下溯造型”技能。然而,我们知道一个上溯造型必定是安详的;基本类不行能再拥有一个比衍生类更大的接口。因此,我们通过基本类接口发送的每一条动静都必定可以或许吸收到。但在举办下溯造型的时候,我们(举个例子来说)并不真的知道一个几许形状实际是一个圆,它完全大概是一个三角形、方形可能其他形状。
为办理这个问题,必需有一种步伐可以或许担保下溯造型正确举办。只有这样,我们才不会冒然造型成一种错误的范例,然后发出一条工具不行能收到的动静。这样做长短常不安详的。
在某些语言中(如C++),为了举办担保“范例安详”的下溯造型,必需采纳非凡的操纵。但在Java中,所有造型城市自动获得查抄和核实!所以纵然我们只是举办一次普通的括弧造型,进入运行期今后,仍然会毫无包涵地对这个造型举办查抄,担保它简直是我们但愿的那种范例。假如不是,就会获得一个ClassCastException(类造型违例)。在运行期间对范例举办查抄的行为叫作“运行期范例标识”(RTTI)。下面这个例子向各人演示了RTTI的行为:
//: RTTI.java // Downcasting & Run-Time Type // Identification (RTTI) import java.util.*; 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。我们可看到这会在对数组x(位于main()中)举办初始化的时候产生。由于数组中的两个工具都属于Useful类,所以可将f()和g()要领同时发给它们两个。并且如果试图挪用u()(它只存在于MoreUseful),就会收到一条编译期堕落提示。
若想会见一个MoreUseful工具的扩展接口,可试着举办下溯造型。假如它是正确的范例,这一动作就会乐成。不然,就会获得一个ClassCastException。我们不必为这个违例编写任何非凡的代码,因为它指出的是一个大概在措施中任那里所产生的一个编程错误。
RTTI的意义远不只仅反应在造型处理惩罚上。譬喻,在试图下溯造型之前,可通过一种要领相识本身处理惩罚的是什么范例。整个第11章都在报告Java运行期范例标识的方方面面。