在Java中禁止继承的好理由?

Good reasons to prohibit inheritance in Java?

有什么好的理由来禁止Java中的继承,例如使用一个单独的、私有的无参数构造函数来使用最终类或类?最终确定方法的好理由是什么?


你最好的参考是Joshua Bloch的优秀著作《有效Java》的第19条,名为"设计和文档继承或其他禁止"。(这是第二版的第17项,第一版的第15项。)你真的应该读一下,但我要总结一下。

如果祖先不是被设计来继承的,那么继承类与父类之间的交互可能会令人惊讶和不可预测。

因此,类应该分为两类:

  • 设计用于扩展的类,并且有足够的文档来描述应该如何完成

  • 标记为final的类

  • 如果您编写的是纯内部代码,这可能有点过分了。但是,在类文件中添加五个字符所需的额外工作非常少。如果您只是为内部消耗而写,那么未来的编码人员总是可以删除"final",您可以将其视为一个警告:"这个类的设计思想中没有继承性"。


    您可能希望使一个方法成为最终方法,这样重写类就不能更改其他方法所依赖的行为。在构造函数中调用的方法通常被声明为final,这样在创建对象时就不会有任何不愉快的意外。


    使类最终化的一个原因是,如果您想强制组合而不是继承。这通常是为了避免类之间的紧密耦合。


    有3个用例可以用于最终方法。

  • 以避免派生类重写特定的基类功能。
  • 这是出于安全目的,其中基类提供框架的一些重要核心功能,而派生类不应该更改框架。
  • 最终方法比实例方法更快,因为最终方法和私有方法不使用虚拟表概念。所以在有可能的地方,试着使用最后的方法。
  • 课程最终确定的目的:

    所以没有人能够扩展这些类并改变它们的行为。

    包装类整数是最后一个类。如果该类不是最终类,那么任何人都可以将integer扩展到自己的类中,并更改integer类的基本行为。为了避免这种情况,Java将所有包装类作为最终类。


    您可能希望创建不可变的对象(http://en.wikipedia.org/wiki/immutable_object),您可能希望创建一个singleton(http://en.wikipedia.org/wiki/singleton_pattern),或者出于效率、安全或安全的原因,您可能希望阻止某人重写该方法。


    继承就像一把链锯-非常强大,但在坏人手中却很可怕。或者您设计了一个要从中继承的类(这会限制灵活性并花费更长的时间),或者您应该禁止它。

    查看有效的Java第二版项目16和17,或我的博客帖子"遗产税"。


    六羟甲基三聚氰胺六甲醚。。。我可以想到两件事:

    您可能有一个处理某些安全问题的类。通过对其进行子类化并向系统提供子类化版本,攻击者可以绕过安全限制。例如,您的应用程序可能支持插件,如果一个插件可以将您的安全相关类划分为子类,那么它可以使用这个技巧以某种方式将它的子类版本走私到适当的位置。但是,这是Sun必须处理的关于小程序之类的问题,可能不是这样一个现实的情况。

    一个更现实的方法是避免对象变为可变的。例如,由于字符串是不可变的,因此您的代码可以安全地保留对它的引用。

    1
     String blah = someOtherString;

    而不是先复制字符串。但是,如果可以对字符串进行子类化,则可以向其中添加允许修改字符串值的方法,现在没有任何代码可以再依赖于,如果字符串只是如上所述复制字符串,那么它将保持不变,而必须复制字符串。


    如果您将类和方法标记为最终的,您可能会注意到一个小的性能提升,因为运行时不必查找为给定对象调用的正确类方法。非final方法被标记为virtual,以便在需要时对其进行适当扩展,final方法可以在类中直接链接或内联编译。


    另外,如果您正在编写一个商业性的封闭源代码类,您可能不希望人们能够直接更改功能,特别是如果您需要对其提供支持,并且人们已经重写了您的方法,并且抱怨调用它会产生意想不到的结果。


    阻止人们做那些会使自己和他人困惑的事情。想象一个物理库,其中有一些定义的常量或计算。如果不使用final关键字,有人可能会过来重新定义基本计算或永远不会改变的常量。


    您希望使一个方法成为最终方法,这样重写类就不会改变它的行为。当您希望能够更改行为时,请将该方法设为公共方法。当您重写一个公共方法时,它可以被更改。