12

Are there any general guidelines as to when to make a class final?

I thought it was if you did not want people extending your class, but that seems slightly.... naive??

user997112
  • 29,025
  • 43
  • 182
  • 361
  • 1
    I think there are a lot of questions like this here: http://stackoverflow.com/questions/2169668/why-would-you-make-a-whole-class-sealed-final for example – Roman Goyenko Jul 30 '12 at 22:05
  • 1
    Consider the class String, it is final. It was required to be kept final and not allowing extending because JVM maintains string-pools, they are immutable. If anyone override it, that would create problems for the JVM, it may not be able to maintain any string-pools because JVM is not aware how how the extended class may have implemented some of it methods and may create larger untraceable problems. So, IT ALL DEPENDS and would require a great design decision whether to provide a class as FINAL or not. We definitely do not use FINAL for classes on a day-to-day basis. – devang Jul 30 '12 at 22:11
  • What *other* criterion could there possibly be? – user207421 Jul 30 '12 at 23:13

3 Answers3

12

Making a class final only prevents it from being extended as you note. Why would you want to do that?

  • One typical use case is to guarantee immutability. If you design an immutable class but don't make it final, it can be extended in a mutable way. This can in turn lead to a subclass corrupting a class invariant or creating concurrency issues.

  • You could also simply mark a class as final to document the fact that it is not designed to be extended. See for example Effective Java #17: "Design and document for inheritance or else prohibit it".

assylias
  • 321,522
  • 82
  • 660
  • 783
  • If the fields are themselves final, this is (theoretically) not an issue. Though reflection breaks all the rules... – user949300 Jul 30 '12 at 22:15
  • @user949300 Agreed, but a good counter-example is BigDecimal, which is immutable but not final, and has some non-final fields. It should have been final in the first place. – assylias Jul 30 '12 at 22:18
  • 1
    @assylias, although I marked you up, I don't like to see final classes in poorly maintained libraries. This is because it restricts upstream users (me!) from implementing workarounds by extending the class and `@Override`ing offending code. If the library is actively maintained, then Bloch has it absolutely right. – fommil Jul 30 '12 at 22:19
  • Love: Design and document for inheritance or else prohibit it – Isabelle Jun 28 '17 at 20:47
  • Avoid, if possible, making a class final if there's any chance someone will need to mock it for testing purposes. They (and I) will curse you. (And, yes, PowerMock can mock final classes... and "worse you cannot say of it.") – Charles Roth May 16 '18 at 16:42
  • @CharlesRoth In that case you can also make an interface that the final class implements, and only pass the interface around. Easy to mock. – assylias May 17 '18 at 09:20
  • @assylias Totally agree. (My original comment implies it: if there's an interface, then I don't need to mock the class.) In fact, that suggests a possible guideline: don't make a class final w/o an interface, unless you have (e.g. String above) a damn good reason. :-) – Charles Roth Jul 14 '18 at 14:23
5

Ideally, you have read Josh Bloch and designed your class for perfectly working inheritance. But, in practice, my (IMHO) answer to making a class final is

Do you trust (or want) others to extend it?

If it is a super-critical class like String or some security related class, yes, definitely make it final.

If you are doing real fancy stuff and the class would be difficult to extend properly, consider making it final, depending on the skills you expect those using the class to have. Also depends on whether this is a general purpose library or some company/project specific code, and whether is it for a website with Squirrel videos or a heart pacemaker - i.e., how badly will a poor subclass break things???

If you aren't doing anything all that fancy, don't annoy users by making it final. I have often cursed Java for making classes like Double final.

user949300
  • 15,364
  • 7
  • 35
  • 66
  • +1 real life counterpart of my theoretical-we-live-in-a-perfect-world answer ;-) – assylias Jul 30 '12 at 22:23
  • 2
    @user949300 how badly will a poor subclass break things? In a closed system, you can probably patch any problems you encounter in the code where the class is used. In an open system this could render the class impossible to be fixed properly, you users may probably have to live with the problem forever, simply because there are a thousands of other users out there trusting on the contract of a broken API, users that have extended the class and propagated its flaws to yet more APIs. – Edwin Dalorzo Jul 30 '12 at 22:45
  • 2
    @EdwinDalorzo OTOH, if the class if `final` and doesn't anticipate everything users might want to do (which is 100% certain to happen) the workarounds ("treatment") might be worse than the disease. So "it depends". – user949300 Jul 30 '12 at 22:50
  • @user949300 Agreed 100%. That's why API design is an art. I most probably would get it wrong every time ;-) – Edwin Dalorzo Jul 30 '12 at 22:53
  • I think almost everybody gets it wrong every time. – user949300 Jul 30 '12 at 23:08
4

It is well established that inheritance breaks encapsulation. Allan Snyder in his paper Encapsulation and inheritance in object-oriented programming languages demonstrates the care you must exercise with inheritance.

Josua Bloch in his book Effective Java recommends that you design and document your classes to be inherited or else you prohibit it, precisely referring to the problems already known to Snyder.

If at some point you are not sure how your classes can be extended in the future or if you have no intention whatsoever that they actually be extended, then you are probably better off making them final. You can always open them for extension later, but the contrary (above all if you are building an open system) can be a real cause of pain, if not impossible depending of the circumstances.

The researches Mikhajlov and Sekerinski in their paper A Study of the Fragile Base Class demonstrate the array of problems you may have when improperly using inheritance which may give you a broader idea of why this could be important.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205