I said final classes are evil and that post got some attention with interesting comments. Maybe because of the title and the tone I wrote it, a few comments didn’t get my real intention and perhaps I should have been more explicit about it. Go ahead and read it. I’ll wait.
Anyway, I thought I’d expand a little more on that subject, explaining my motivation to write that post and going through the topics I think were raised by my dear readers.
First off, final classes are evil for testing. And that’s what it was all about in my previous post.
If you depend on a final class, your code will be harder to test. Unless the final class provides an interface that captures its intent - or you wrap that dependency.
But this affirmation has some implications that were pointed out by a few comments, some of which I agree with - others, not so much. So let’s start!
- Immutability
Someone said “Why make a class final ? To make it immutable”. This is not entirely true. Only by marking it final you do not ensure immutability. There is no point in doing that if you provide mutators - e.g. setters. - and don’t declare your members private and final.
I think it’s important to make this clear and understand that the immutability part you achieve by marking a class final is the one of preventing inheritance. Subclasses could possibly contain malicious/careless code and change the internal state of the class.
But there is another way of preventing subclassing without marking the parent final: declare its constructor private and provide a static factory.
- Designing for extensibility
This is hard. It basically means that if you don’t mark a class final, you should document it for inheritance.
And this is why inheritance is, in general, a bad OO practice. By documenting the class you basically break encapsulation since you tell the world about your internals.
Therefore, the recommendation is to mark a class final if you’re not sure if it’s safe to subclass it - or if you just don’t wanna bother writing documentation and thinking too much about your “client” subclasses.
- Coding against interfaces
This one is simple but yet often forgotten. Do not code to concrete classes. Always choose interfaces where possible.
It roughly means to do this:
List args = new ArrayList();
instead of this:
ArrayList args = new ArrayList();
By doing so you have the flexibility to not care about the implementation you’re working with, as long as it obeys the interface. That way, the implementations can be swapped at any time without breaking any client’s code.
- The problem with testing
All items listed here so far are widely regarded as best practices and the bullet I raised about hard testing usually happens when you “violate” some of them.
Specifically, if you decide not to design a class for inheritance and mark it as final, it’s wise - in my opinion - to try and capture the class’s intent through an interface.
That way you can safely mark your class final and users of your class can easily use the interface to extend it - by favoring composition over inheritance - or by providing it to mocking frameworks for easy testing.
- Conclusion
I don’t really think there is a rule of thumb here. Java’s standard library shows many examples of both approaches and some of them are now considered bad practices but yet are there for backward compatibility. Nevertheless, these are points to consider when designing your classes.
As pointed out by Josua Bloch in his awesome book Effective Java, “If a concrete class does not implement a standard interface, then you may inconvenience some programmers by prohibiting inheritance”.
As usual, comments are more than welcome


[...] Update: Go ahead and read this post in its entirety - including the comments. Then, read my other post where I expand the subject a little more. [...]
Nice post, I think now you made your point clearer.
About immutability, I think people are confusing final classes and immutable classes. Final classes, which is what you point as “evil for testing”, mean don´t allowing your classes to be subclassed; immutable classes mean don´t allowing your objects´ state to be changed after its creation, i.e., creating a constructor which receives every class attribute as a parameter (and making a safe copy of every object you get as a parameter) and don´t creating setters for your class attributes.
Right on!
That’s exactly what I said in the first item, Immutability. You can certainly have mutable final classes. I’m glad all these points are clearer now!
tks for stopping by!
With regards to (unit) testing, the cause of the difficulty is not that a given class on which the tested unit depends was declared “final”, but that a poor unit testing tool for the isolation of dependencies is being used.
The fact is, applying the “final” modifier to methods and/or classes is a perfectly valid OO design mechanism, so it should not be ruled out. Not only does it discourage the abuse of inheritance, but it also brings practical benefits by allowing a static analysis tool (such as IDEA) to detect certain forms of unused code.
I think the citation from the Effective Java book (page 92 of the 2nd edition) is somewhat misleading. If you read the two previous paragraphs in the book, it should be clear that the author (J. Bloch) wasnt’t trying to encourage the creation of a separate Java interface for each “final” class. Instead, he was simply discussing the potential consequences of the decision of making a concrete class non-overridable. One such consequence could be to “inconvenience some programmers” that wish for whatever reason to create a subclass. Sure, it might occur in some cases (which should be really rare, in my experience). Note that the author’s advice (emphasized in the book, page 91) is to “prohibit subclassing in classes that are not designed and documented to be safely subclassed”. And the vast majority of classes in a system fit this criteria.
Hi Rogério! Tks for dropping by again
Would you mind elaborating a little bit more on your first comment, where you say “but that a poor unit testing tool for the isolation of dependencies is being used”.
Note that while I do agree final classes - and members - are a valid OO practice, my sole point was to say it can make things harder to test. This inconvenience can be bypassed by wrapping the dependency with a common interface. Which is ok. But the way I see it, if I design a class that by any means can have external code depending on it, I’ll try to implement an interface - unless I design it for inheritance.