在Java中禁止inheritance的好理由?

在Java中禁止inheritance的好理由是什么,例如通过使用单个私有的无参数构造函数来使用最终的类或类? 做出最终方法的好理由是什么?

这里最好的参考是Joshua Bloch出色的书“Effective Java”中的第17项(第一版中的15),称为“inheritance或禁止它的devise和文档”。 你应该看看,但我会总结一下。

如果祖先不是被devise为遗传的,那么遗传类与父母的交互可能是令人惊讶和不可预测的。

因此,课程应该有两种:

  1. devise的可以扩展 ,并有足够的文档来描述应该如何完成

  2. 标记为最终

如果你写纯粹的内部代码,这可能有点矫枉过正。 然而,将五个字符添加到类文件所涉及的额外工作量非常小。 如果你只是为了内部消费而编写代码,那么未来的编码器总是可以删除“最终” – 你可以把它看作是一个警告,说“这个类不是为了inheritance而devise的”。

你可能想要做一个方法final,这样覆盖类不能改变其他方法中的行为。 在构造函数中调用的方法通常被声明为final,因此在创build对象时不会有任何不愉快的意外。

如果你想强制合成而不是inheritance,那么做一个类的最后一个原因是。 这通常是避免类之间紧密耦合的需要。

你可能想创build一个不可变的对象( http://en.wikipedia.org/wiki/Immutable_object ),你可能想创build一个单例( http://en.wikipedia.org/wiki/Singleton_pattern ),或者你可能想要为了防止有人为了效率,安全或安全的原因而超越方法。

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

  1. 避免派生类重写特定的基类function。
  2. 这是为了安全目的,其中基类提供了框架的一些重要的核心function,派生类不应该改变它。
  3. 最终的方法比实例方法快,因为最终的和私有的方法没有使用虚拟表的概念。 所以,如果有可能的话,尝试使用最终的方法。

决定课程的目的:

所以没有任何一个机构可以延伸这些阶级并改变他们的行为

例如:包装类Integer是一个最终的类。 如果这个类不是最终的,那么任何人都可以将Integer扩展到他自己的类中,并改变整数类的基本行为。 为了避免这种情况,java把所有的包装类作为final类。

inheritance就像一把电锯 – 非常强大,但在错误的手中可怕。 要么你devise一个类inheritance(这可能会限制灵活性,并采取更长的时间),或者你应该禁止它。

请参阅有效Java第2版第16和17项或我的博客文章“inheritance税” 。

嗯…我可以想到两件事情:

你可能有一个类来处理某些安全问题。 通过inheritance它并为系统提供它的子版本,攻击者可以规避安全限制。 例如,你的应用程序可能支持插件,如果一个插件可以inheritance你的安全相关的类,它可以使用这个技巧以某种方式走私它的一个子版本。 然而,这是Sun所要处理的小应用程序等问题,也许不是这样一个现实的案例。

更现实的一个是避免一个对象变得可变。 例如,因为string是不可变的,所以你的代码可以安全地保持对它的引用

  String blah = someOtherString; 

而不是先复制string。 但是,如果您可以对String进行子类化,则可以向其中添加允许修改string值的方法,现在没有代码可以再依赖该string保持不变,只要它像上面那样复制string就可以了,串。

阻止人们做出让自己和他人混淆的事情。 想象一下你有一个定义常量或计算的物理库。 在不使用final关键字的情况下,有人可以前来重新定义永远不会改变的基本计算或常量。

另外,如果你正在编写一个商业闭源类,你可能不希望人们能够改变这个function,特别是当你需要支持它时,人们已经重写了你的方法,并且抱怨说调用它意外的结果。

如果将类和方法标记为final,则可能会注意到性能提升很小,因为运行时不必查找正确的类方法来调用给定的对象。 非最终方法被标记为虚拟的,以便在需要时可以正确地扩展它们,最终的方法可以直接链接或者在类中内联编译。

你想要做一个方法的最终使得重写类不会改变它的行为。 如果您想要更改行为,请使该方法公开。 当你重写一个公共方法时,它可以被改变。