🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## [本章小结](https://lingcoder.gitee.io/onjava8/#/book/19-Type-Information?id=%e6%9c%ac%e7%ab%a0%e5%b0%8f%e7%bb%93) RTTI 允许通过匿名类的引用来获取类型信息。初学者极易误用它,因为在学会使用多态调用方法之前,这么做也很有效。有过程化编程背景的人很容易把程序组织成一系列`switch`语句,你可以用 RTTI 和`switch`实现功能,但这样就损失了多态机制在代码开发和维护过程中的重要价值。面向对象编程语言是想让我们尽可能地使用多态机制,只在非用不可的时候才使用 RTTI。 然而使用多态机制的方法调用,要求我们拥有基类定义的控制权。因为在你扩展程序的时候,可能会发现基类并未包含我们想要的方法。如果基类来自别人的库,这时 RTTI 便是一种解决之道:可继承一个新类,然后添加你需要的方法。在代码的其它地方,可以检查你自己特定的类型,并调用你自己的方法。这样做不会破坏多态性以及程序的扩展能力,因为这样添加一个新的类并不需要修改程序中的`switch`语句。但如果想在程序中增加具有新特性的代码,你就必须使用 RTTI 来检查这个特定的类型。 如果只是为了方便某个特定的类,就将某个特性放进基类里边,这将使得从那个基类派生出的所有其它子类都带有这些可能毫无意义的东西。这会导致接口更加不清晰,因为我们必须覆盖从基类继承而来的所有抽象方法,事情就变得很麻烦。举个例子,现在有一个表示乐器`Instrument`的类层次结构。假设我们想清理管弦乐队中某些乐器残留的口水,一种办法是在基类`Instrument`中放入`clearSpitValve()`方法。但这样做会导致类结构混乱,因为这意味着打击乐器`Percussion`、弦乐器`Stringed`和电子乐器`Electronic`也需要清理口水。在这个例子中,RTTI 可以提供一种更合理的解决方案。可以将`clearSpitValve()`放在某个合适的类中,在这个例子中是管乐器`Wind`。不过,在这里你可能会发现还有更好的解决方法,就是将`prepareInstrument()`放在基类中,但是初次面对这个问题的读者可能想不到还有这样的解决方案,而误认为必须使用 RTTI。 最后一点,RTTI 有时候也能解决效率问题。假设你的代码运用了多态,但是为了实现多态,导致其中某个对象的效率非常低。这时候,你就可以挑出那个类,使用 RTTI 为它编写一段特别的代码以提高效率。然而必须注意的是,不要太早地关注程序的效率问题,这是个诱人的陷阱。最好先让程序能跑起来,然后再去看看程序能不能跑得更快,下一步才是去解决效率问题(比如使用 Profiler)\[^5\]。 我们已经看到,反射,因其更加动态的编程风格,为我们开创了编程的新世界。但对有些人来说,反射的动态特性却是一种困扰。对那些已经习惯于静态类型检查的安全性的人来说,Java 中允许这种动态类型检查(只在运行时才能检查到,并以异常的形式上报检查结果)的操作似乎是一种错误的方向。有些人想得更远,他们认为引入运行时异常本身就是一种指示,指示我们应该避免这种代码。我发现这种意义的安全是一种错觉,因为总是有些事情是在运行时才发生并抛出异常的,即使是在那些不包含任何`try`语句块或异常声明的程序中也是如此。因此,我认为一致性错误报告模型的存在使我们能够通过使用反射编写动态代码。当然,尽力编写能够进行静态检查的代码是有价值的,只要你有这样的能力。但是我相信动态代码是将 Java 与其它诸如 C++ 这样的语言区分开的重要工具之一。 \[^1\]: 特别是在过去。但现在 Java 的 HTML 文档有了很大的提升,要查看基类的方法已经变得很容易了。 \[^2\]: 这是极限编程(XP,Extreme Programming)的原则之一:“Try the simplest thing that could possibly work,实现尽最大可能的简单。” \[^3\]: 最著名的例子是 Windows 操作系统,Windows 为开发者提供了公开的 API,但是开发者还可以找到一些非公开但是可以调用的函数。为了解决问题,很多程序员使用了隐藏的 API 函数。这就迫使微软公司要像维护公开 API 一样维护这些隐藏的 API,消耗了巨大的成本和精力。 \[^4\]: 比如,Python 中在元素前面添加双下划线`__`,就表示你想隐藏这个元素。如果你在类或者包外面调用了这个元素,运行环境就会报错。 \[^5\]: 译者注:Java Profiler 是一种 Java 性能分析工具,用于在 JVM 级别监视 Java 字节码的构造和执行。主流的 Profiler 有 JProfiler、YourKit 和 Java VisualVM 等。