203

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?

cretzel
  • 19,864
  • 19
  • 58
  • 71
  • 1
    Pedantry: The default constructor is the one generated for you by the Java compiler if you don't explicitly write one in your code. You mean the no argument constructor. – John Topley Oct 20 '08 at 15:21
  • Isn't that the "implicit default constructor"? – cretzel Oct 20 '08 at 15:28
  • 2
    "You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors." http://java.sun.com/docs/books/tutorial/java/javaOO/constructors.html – John Topley – John Topley Oct 20 '08 at 15:37

11 Answers11

202

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.

The interaction of inherited classes with their parents can be surprising and unpredictable if the ancestor wasn't designed to be inherited from.

Classes should therefore come in two kinds:

  1. Classes designed to be **extended**, and with enough documentation to describe how it should be done

  2. 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 consumption, 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".

Ziyaddin Sadigov
  • 8,893
  • 13
  • 34
  • 41
DJClayworth
  • 26,349
  • 9
  • 53
  • 79
  • 1
    That's a good answer, but it's a little bit of overkill in most situations. – wprl Oct 20 '08 at 15:12
  • 6
    In my experience this is not overkill if anyone besides me will be using the code. I have never understood why Java has methods overridable by default. – Eric Weilnau Oct 20 '08 at 15:36
  • 11
    To understand some of Effective Java, you need to understand Josh's take on design. He says [something like] you should always design class interfaces as if they were a public API. I think the majority opinion is that this approach is usually too heavy and inflexible. (YAGNI, etc.) – Tom Hawtin - tackline Oct 20 '08 at 15:44
  • 11
    Good answer. (I can't resist pointing out that it's six characters, as there's also a space... ;-) – joel.neely Feb 08 '09 at 13:18
  • 49
    Please note, that making classes final might make testing harder (harder to stub or mock) – notnoop Dec 16 '09 at 22:59
  • 11
    If the final class is writing to an interface, then mocking should not be a problem. – Fred Haslam May 18 '10 at 16:29
  • 4
    it is very hard to remove the final on an interface you do not have source for, and being able to subclass to override a method may be essential. – Thorbjørn Ravn Andersen Jul 09 '10 at 03:44
  • 1
    To save people looking it up, "Design and document for inheritance or else prohibit it" is Item 17 in the second edition. – freshtop Dec 09 '14 at 01:01
  • 1
    @ThorbjørnRavnAndersen you mean a class? An interface (or even an abstract class) with final modifier doesn't sound like a good design. – amertkara Apr 29 '15 at 15:39
  • 3
    Not this is the difference between library/framework writers and application writers. What Tom Hawtin describes as "too heavy and inflexible" becomes downright crucial when you inherit code written by others and can't deprecate any of the mistakes in the design because the original developers thought everything should be public. In general, you should always design package level final classes that implement methods on public interfaces. If you need to change the interface later, you use ADAPTER. Failure to do this means design mistakes can never be fixed once software is deployed. i.e) Java – Visionary Software Solutions Jul 19 '15 at 20:15
  • 2
    The struggle I have with marking everything final by default is that it assumes a developer who didn't take the effort to make a class suitable for extension is somehow going to spend the time making sure it implements a well-designed interface to facilitate testing. Either the dev is lazy, in which case there is no interface and it's marked final, or the dev is details-oriented in which case the class supports extension and does not need to be `final`. – GuyPaddock Oct 27 '17 at 17:16
  • I ve started reading "Effective Java" which is mentioned in this post. It seems good to understand best practices – Rakesh L Mar 18 '18 at 16:15
31

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.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • Didn't quite understand this answer. If you don't mind, could you explain what you mean by "overriding classes can't change behaviour that is counted on in other methods"? Am asking firstly because I didn't understand the sentence, and secondly because Netbeans is recommending that one of my functions I'm calling from the constructor, should be `final`. – Nav Feb 25 '16 at 08:11
  • 1
    @Nav If you make a method final, then an overriding class won't be able to have its own version of that method (or it will be a compile error). That way you know that the behavior you implement in that method won't change later when someone else extends the class. – Bill the Lizard Feb 25 '16 at 12:11
  • C# will warn you if you call virtual methods from a constructor. Methods called in constructors sort of mirrors this. – Petter Hesselberg Nov 07 '21 at 19:23
22

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.

John Topley
  • 113,588
  • 46
  • 195
  • 237
18

There are 3 use cases where you can go for final methods.

  1. To avoid derived class from overriding a particular base class functionality.
  2. 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.
  3. 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.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
user1923551
  • 4,684
  • 35
  • 29
  • Not very much convinced with your example. If that is the case, then why not make the methods and variables final instead of making the whole class final. Can you please edit your answer with the details. – Rajkiran Jan 20 '15 at 18:10
  • 4
    Even if you make all the variables and methods as final, still others can inherit your class and add extra functionality and change the basic behavior of your class. – user1923551 May 07 '15 at 09:18
  • 7
    > If that class is not final, then any one can extend Integer into his own class and change the basic behavior of integer class. Let's say this was allowed and this new class was called ```DerivedInteger```, it still doesn't change the original Integer class, and whoever uses ```DerivedInteger``` does so at their own risk, so I still don't get why it's a problem. – Siddhartha Jul 05 '17 at 22:03
13

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.

Ray Tayek
  • 9,841
  • 8
  • 50
  • 90
6

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".

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    The link to the blog post is broken. Also, do you think you could elaborate a bit more on this? –  Sep 22 '14 at 05:27
  • @MichaelT: Fixed the link, thanks - follow it for more elaboration :) (I don't have the time to add to this right now, I'm afraid.) – Jon Skeet Sep 22 '14 at 05:46
  • @JonSkeet, The link to the blog post is broken. – Lucifer Mar 27 '15 at 01:31
  • @Kedarnath: It works for me... it *was* broken for a while, but it's now pointing to the correct page, on codeblog.jonskeet.uk... – Jon Skeet Mar 27 '15 at 06:44
5

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.

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.

Mecki
  • 125,244
  • 33
  • 244
  • 253
3

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.

Anson Smith
  • 6,194
  • 1
  • 23
  • 10
  • 4
    There's something I don't understand about that argument - if someone did change those calculations/constants that shouldn't change - aren't any failures due to that 100% their fault? In other words, how does the change benefit anything? – matt b Oct 20 '08 at 15:18
  • Yes, it's technically "their" fault but imagine someone else using the library that's not been made aware of the changes, could lead to confusion. I have always thought that that was the reason many of the Java Base classes were marked final, to stop people form altering basic functionality. – Anson Smith Oct 20 '08 at 15:28
  • @matt b - You seem to be assuming that the developer who made the change did so knowingly or that they would care that it was their fault. If someone besides me will be using my code, I will mark it final unless it is meant to be changed. – Eric Weilnau Oct 20 '08 at 15:33
  • This is actually a different usage of 'final' from the one asked about. – DJClayworth Oct 20 '08 at 17:53
  • This answer seems to confuse inheritance and mutability of individual fields with the ability to write a subclass. You can mark individual fields and methods as final (preventing their redefinition) without prohibiting inheritance. – joel.neely Feb 08 '09 at 13:25
2

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.

DavidG
  • 1,796
  • 4
  • 21
  • 33
2

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.

seanalltogether
  • 3,542
  • 3
  • 26
  • 24
  • 2
    I believe this is a myth, since current generation VMs should be able to optimize and deoptimize as needed. I remember seeing some bencharmking this and classifying it as a myth. – Miguel Ping Oct 20 '08 at 17:53
  • 1
    The difference in code generation is not a myth, but maybe the performance gains are. As I said its a small gain, one site mentioned a 3.5% performance gain, some higher, which in most cases is not worth going all Nazi on your code. – seanalltogether Oct 21 '08 at 01:07
  • 1
    It is not a myth. In fact, the compiler can only inline V final methods. I am not sure if any JITs "inline" things art runtime but I doubt that it can since you may be loading a derived class later. – Uri Nov 01 '08 at 17:51
  • 1
    Microbenchmark==grain-of-salt. That said, after 10B cycle warmup, avg over 10B calls shows essentially no difference under Eclipse on my laptop. Two methods returning String, final was 6.9643us, non-final was 6.9641us. That delta is background noise, IMHO. – joel.neely Feb 08 '09 at 14:17
0

You want to make a method final so that overriding classes does not change its behavior. When you want to be able to change the behavior make the method public. When you override a public method it can be changed.