在Java中禁止继承有什么好理由,例如使用单个私有无参数构造函数使用final类或类?使方法最终成功的理由是什么?
答案 0 :(得分:165)
这里你最好的参考是Joshua Bloch的优秀书籍“Effective Java”的第19项,名为“继承的设计和文件,或者禁止它”。 (这是第二版中的第17项和第一版中的第15项。)你应该读它,但我会总结一下。
如果祖先不是为了继承而设计的,那么继承类与父母的交互可能会令人惊讶且难以预料。
因此,课程应分为两类:
类旨在扩展 ,并提供足够的文档来描述应该如何完成
类标记为最终
如果您正在编写纯粹的内部代码,这可能有点矫枉过正。但是,在类文件中添加五个字符所需的额外工作量非常小。如果你只是为内部消费而写,那么未来的编码器总是可以删除'final' - 你可以把它想象成一个警告,说“这个类的设计并没有考虑到继承”。
答案 1 :(得分:21)
您可能希望将方法设为final,以便覆盖类不能更改其他方法中所依赖的行为。构造函数中调用的方法通常被声明为final,因此在创建对象时不会产生任何令人不快的意外。
答案 2 :(得分:17)
使一个类最终成功的一个原因是如果你想强制组合而不是继承。这通常是希望避免类之间的紧密耦合。
答案 3 :(得分:13)
有3个用例可供您使用最终方法。
最终成绩的目的:
所以没有人可以扩展这些类并改变他们的行为。
例如:Wrapper类Integer是一个最终类。如果该类不是final,那么任何人都可以将Integer扩展到他自己的类中并更改整数类的基本行为。为了避免这种情况,java将所有包装类作为最终类。
答案 4 :(得分:12)
您可能想要创建不可变对象(http://en.wikipedia.org/wiki/Immutable_object),您可能想要创建单例(http://en.wikipedia.org/wiki/Singleton_pattern),或者您可能希望阻止某人因效率,安全性而覆盖该方法或安全。
答案 5 :(得分:6)
继承就像一个电锯 - 非常强大,但在错误的手中可怕。要么设计一个要继承的类(这可以限制灵活性并且需要更长的时间),或者你应该禁止它。
请参阅有效的Java第2版第16和17项,或我的博文"Inheritance Tax"。
答案 6 :(得分:4)
嗯......我能想到两件事:
您可能有一个处理某些安全问题的课程。通过对其进行子类化并为系统提供子类化版本,攻击者可以绕过安全限制。例如。你的应用程序可能支持插件,如果一个插件可以只是你的安全相关类的子类,它可以使用这个技巧以某种方式将它的子类版本走私到位。然而,这是Sun必须处理的关于applet等的事情,可能不是这样一个现实的案例。
更现实的是避免对象变得可变。例如。因为字符串是不可变的,所以你的代码可以安全地保持对它的引用
String blah = someOtherString;
而不是先复制字符串。但是,如果您可以继承String,则可以向其添加允许修改字符串值的方法,现在没有代码可以再依赖于字符串将保持不变,如果它只是复制上面的字符串,而是必须复制字符串。
答案 7 :(得分:1)
阻止人们做一些可能让自己和他人混淆的事情。想象一下物理库,你有一些定义的常量或计算。如果不使用final关键字,有人可能会出现并重新定义基本的计算或常量,这些计算或常量永远不会改变。
答案 8 :(得分:1)
此外,如果您正在编写商业闭源类,您可能不希望人们能够更改功能,特别是如果您需要支持它并且人们已经覆盖您的方法并且抱怨调用它会产生意想不到的结果。
答案 9 :(得分:1)
如果将类和方法标记为final,您可能会注意到性能的小幅提升,因为运行时不必查找正确的类方法来调用给定对象。非最终方法被标记为虚拟,以便在需要时可以正确扩展,最终方法可以在类中直接链接或编译。
答案 10 :(得分:0)
您希望将方法设为final,以便覆盖类不会更改其行为。当您希望能够更改行为时,请将该方法设为公开。当您覆盖公共方法时,可以更改它。