views:

770

answers:

9

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?

+10  A: 

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
+22  A: 

Your best reference here is Item 15 of Joshua Bloch's excellent book "Effective Java", called "Design and document for inheritance or else prohibit it". You should really read it, but I'll summarize.

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 a) classes designed to be extended, and with enough documentation to describe how it should be done b) 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".

DJClayworth
That's a good answer, but it's a little bit of overkill in most situations.
SoloBold
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
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
Good answer. (I can't resist pointing out that it's six characters, as there's also a space... ;-)
joel.neely
Is there a way for me to mark this as the "accepted answer" ;)
allyourcode
Please note, that making classes final might make testing harder (harder to stub or mock)
notnoop
If the final class is writing to an interface, then mocking should not be a problem.
Fred Haslam
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
+3  A: 

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
+1  A: 

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  A: 

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
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
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
@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
@Anson, @Eric - good points. thanks for clearing that up
matt b
This is actually a different usage of 'final' from the one asked about.
DJClayworth
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
+1  A: 

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
+1  A: 

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
+1  A: 

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  A: 

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