在 Java 中禁止继承的充分理由?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/218744/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Good reasons to prohibit inheritance in Java?
提问by cretzel
What are good reasons to prohibit inheritance in Java, for example by using final classes or classes using a single, private parameterless constructor? What are good reasons of making a method final?
在 Java 中禁止继承的充分理由是什么,例如使用最终类或使用单个私有无参数构造函数的类?使方法最终化的充分理由是什么?
采纳答案by DJClayworth
Your best reference here is Item 19 of Joshua Bloch's excellent book "Effective Java", called "Design and document for inheritance or else prohibit it". (It's item 17 in the second edition and item 15 in the first edition.) You should really read it, but I'll summarize.
这里最好的参考是 Joshua Bloch 的优秀著作“Effective Java”的第 19 条,名为“继承的设计和文档,否则禁止它”。(它是第二版的第 17 项和第一版的第 15 项。)你真的应该阅读它,但我会总结一下。
The interaction of inherited classes with their parents can be surprising and unpredicatable if the ancestor wasn't designed to be inherited from.
如果祖先不是为了继承而设计的,继承类与其父类的交互可能会令人惊讶和不可预测。
Classes should therefore come in two kinds :
因此,类应该有两种:
Classes designed to be extended, and with enough documentation to describe how it should be done
Classes marked final
设计用于扩展的类,并有足够的文档来描述它应该如何完成
课程标记为最终
If you are writing purely internal code this may be a bit of overkill. However the extra effort involved in adding five characters to a class file is very small. If you are writing only for internal comsumption then a future coder can always remove the 'final' - you can think of it as a warning saying "this class was not designed with inheritance in mind".
如果您正在编写纯粹的内部代码,这可能有点矫枉过正。然而,将五个字符添加到类文件所涉及的额外工作非常小。如果您只是为内部消费而编写,那么未来的编码人员总是可以删除“最终” - 您可以将其视为警告说“这个类的设计没有考虑到继承”。
回答by Bill the Lizard
You might want to make a method final so that overriding classes can't change behavior that is counted on in other methods. Methods called in constructors are often declared final so you don't get any unpleasant surprises when creating objects.
您可能希望将方法设为 final,以便覆盖类无法更改其他方法所依赖的行为。构造函数中调用的方法通常声明为 final,因此在创建对象时不会出现任何令人不快的意外。
回答by John Topley
One reason to make a class final would be if you wanted to force composition over inheritance. This is generally desirable in avoiding tight coupling between classes.
使类成为 final 的一个原因是,如果您想强制组合而不是继承。这在避免类之间的紧密耦合方面通常是可取的。
回答by Jon Skeet
Inheritance is like a chainsaw - very powerful, but awful in the wrong hands. Either you design a class to be inherited from (which can limit flexibility and take a lot longer) or you should prohibit it.
继承就像一把电锯——非常强大,但如果落入坏人之手,后果不堪设想。要么设计一个要继承的类(这会限制灵活性并花费更长的时间),要么应该禁止它。
See Effective Java 2nd edition items 16 and 17, or my blog post "Inheritance Tax".
请参阅 Effective Java 2nd edition items 16 和 17,或我的博客文章“继承税”。
回答by Anson Smith
To stop people from doing things that could confuse themselves and others. Imagine a physics library where you have some defined constants or calculations. Without using the final keyword, someone could come along and redefine basic calculations or constants that should NEVER change.
阻止人们做可能混淆自己和他人的事情。想象一个物理库,您可以在其中定义一些常量或计算。如果不使用 final 关键字,有人可能会重新定义永远不会改变的基本计算或常量。
回答by Mecki
Hmmm... I can think of two things:
嗯……我能想到两件事:
You might have a class that deals with certain security issues. By subclassing it and feeding your system the subclassed version of it, an attacker can circumvent security restrictions. E.g. your application might support plugins and if a plugin can just subclass your security relevant classes, it can use this trick to somehow smuggle a subclassed version of it into place. However, this is rather something Sun has to deal with regarding applets and the like, maybe not such a realistic case.
您可能有一个处理某些安全问题的类。通过对它进行子类化并向您的系统提供它的子类版本,攻击者可以绕过安全限制。例如,您的应用程序可能支持插件,并且如果插件可以子类化您的安全相关类,它可以使用此技巧以某种方式将其子类化版本走私到位。然而,这是Sun 必须处理的关于applet 等的事情,可能不是那么现实的情况。
A much more realistic one is to avoid an object becomes mutable. E.g. since Strings are immutable, your code can safely keep references to it
一个更现实的方法是避免对象变得可变。例如,由于字符串是不可变的,您的代码可以安全地保留对它的引用
String blah = someOtherString;
instead of copying the string first. However, if you can subclass String, you can add methods to it that allow the string value to be modified, now no code can rely anymore that the string will stay the same if it just copies the string as above, instead it must duplicate the string.
而不是先复制字符串。但是,如果您可以对 String 进行子类化,则可以向其添加允许修改字符串值的方法,现在没有代码可以再依赖于字符串将保持不变,如果它只是像上面那样复制字符串,而是必须复制细绳。
回答by Ray Tayek
you might want to make immutable objects (http://en.wikipedia.org/wiki/Immutable_object), you might want to create a singleton (http://en.wikipedia.org/wiki/Singleton_pattern), or you might want to prevent someone from overriding the method for reasons of efficiency, safety, or security.
您可能想要创建不可变对象(http://en.wikipedia.org/wiki/Immutable_object),您可能想要创建一个单例(http://en.wikipedia.org/wiki/Singleton_pattern),或者您可能想要以防止有人出于效率、安全或保障的原因覆盖该方法。
回答by DavidG
Also, if you are writing a commercial closed source class, you might not want people to be able to change the functionality down the line, especially if u need to give support for it and people have overridden your method and are complaining that calling it gives unexpected results.
此外,如果您正在编写商业闭源类,您可能不希望人们能够更改功能,特别是如果您需要支持它并且人们已经覆盖了您的方法并抱怨调用它给意想不到的结果。
回答by seanalltogether
If you mark classes and methods as final, you may notice a small performance gain, since the runtime doesn't have to look up the right class method to invoke for a given object. Non-final methods are marked as virtual so that they can be properly extended if needed, final methods can be directly linked or compiled inline in the class.
如果您将类和方法标记为 final,您可能会注意到性能的小幅提升,因为运行时不必查找正确的类方法来为给定的对象调用。非final方法被标记为virtual,以便在需要时可以适当扩展它们,final方法可以直接链接或在类中内联编译。
回答by user1923551
There are 3 use cases where you can go for final methods.
有 3 个用例,您可以使用最终方法。
- To avoid derived class from overriding a particular base class functionality.
- This is for security purpose, where base class is giving some important core functionality of the framework where derived class is not supposed to change it.
- Final methods are faster than instance methods, as there is no use of virtual table concept for final and private methods. So where ever there is a possibility, try to use final methods.
- 避免派生类覆盖特定的基类功能。
- 这是出于安全目的,其中基类提供了框架的一些重要核心功能,而派生类不应更改它。
- 最终方法比实例方法更快,因为最终方法和私有方法没有使用虚拟表概念。因此,只要有可能,请尝试使用最终方法。
Purpose for making a class final:
使类最终的目的:
So that no body can extend those classes and change their behavior.
这样任何机构都不能扩展这些类并改变它们的行为。
Eg: Wrapper class Integer is a final class. If that class is not final, then any one can extend Integer into his own class and change the basic behavior of integer class. To avoid this, java made all wrapper classes as final classes.
例如:包装类 Integer 是最终类。如果那个类不是最终的,那么任何人都可以将 Integer 扩展到他自己的类中并改变 integer 类的基本行为。为了避免这种情况,java 将所有包装类都作为最终类。