Good reasons to prohibit inheritance in Java?

66,059

Solution 1

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

Solution 2

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.

Solution 3

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.

Solution 4

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.

Solution 5

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.

Share:
66,059

Related videos on Youtube

cretzel
Author by

cretzel

Java Web Developer

Updated on April 01, 2022

Comments

  • cretzel
    cretzel about 2 years

    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?

    • John Topley
      John Topley over 15 years
      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.
    • cretzel
      cretzel over 15 years
      Isn't that the "implicit default constructor"?
    • John Topley
      John Topley over 15 years
      "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." java.sun.com/docs/books/tutorial/java/javaOO/constructors.ht‌​ml – John Topley
  • matt b
    matt b over 15 years
    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?
  • Anson Smith
    Anson Smith over 15 years
    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.
  • Eric Weilnau
    Eric Weilnau over 15 years
    @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
    Eric Weilnau over 15 years
    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.
  • Brett
    Brett over 15 years
    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.)
  • DJClayworth
    DJClayworth over 15 years
    This is actually a different usage of 'final' from the one asked about.
  • Miguel Ping
    Miguel Ping over 15 years
    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.
  • seanalltogether
    seanalltogether over 15 years
    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.
  • Uri
    Uri over 15 years
    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.
  • joel.neely
    joel.neely over 15 years
    Good answer. (I can't resist pointing out that it's six characters, as there's also a space... ;-)
  • joel.neely
    joel.neely over 15 years
    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.
  • notnoop
    notnoop over 14 years
    Please note, that making classes final might make testing harder (harder to stub or mock)
  • Fred Haslam
    Fred Haslam about 14 years
    If the final class is writing to an interface, then mocking should not be a problem.
  • matbrgz
    matbrgz almost 14 years
    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.
  • Admin
    Admin almost 10 years
    The link to the blog post is broken. Also, do you think you could elaborate a bit more on this?
  • Jon Skeet
    Jon Skeet almost 10 years
    @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.)
  • freshtop
    freshtop over 9 years
    To save people looking it up, "Design and document for inheritance or else prohibit it" is Item 17 in the second edition.
  • Rajkiran
    Rajkiran over 9 years
    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.
  • Lucifer
    Lucifer over 9 years
    @JonSkeet, The link to the blog post is broken.
  • Jon Skeet
    Jon Skeet over 9 years
    @Kedarnath: It works for me... it was broken for a while, but it's now pointing to the correct page, on codeblog.jonskeet.uk...
  • amertkara
    amertkara about 9 years
    @ThorbjørnRavnAndersen you mean a class? An interface (or even an abstract class) with final modifier doesn't sound like a good design.
  • user1923551
    user1923551 about 9 years
    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.
  • Visionary Software Solutions
    Visionary Software Solutions almost 9 years
    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
  • Nav
    Nav over 8 years
    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.
  • Bill the Lizard
    Bill the Lizard over 8 years
    @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.
  • Siddhartha
    Siddhartha almost 7 years
    > 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.
  • GuyPaddock
    GuyPaddock over 6 years
    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.
  • Rakesh L
    Rakesh L over 6 years
    I ve started reading "Effective Java" which is mentioned in this post. It seems good to understand best practices
  • Petter Hesselberg
    Petter Hesselberg over 2 years
    C# will warn you if you call virtual methods from a constructor. Methods called in constructors sort of mirrors this.