8

I have a quick and simple question. I have a habit of making every class 'final' unless of course, it needs to be extended by another.

Is this a bad habit? A good habit? Does it even matter? I understand the effect of the modifier to a class.

Thanks a lot in advance!

Edit: Here is an example code. This class will not be extended by any other classes.

public final class Application {

    /**
     * Starts the application.
     * 
     * @param arguments arguments provided from command-line
     */
    public static void main(String[] arguments) {
        LaunchUtilities util = new LaunchUtilities(new EventHandler());

        try {
            util.addListener(43594);
        } catch (IOException ioe) {
            Logger.getLogger(Application.class.getName()).log(Level.SEVERE, "Could not bind a port to a listener!", ioe);
        }

        util.start();
    }
}
Martin Tuskevicius
  • 2,590
  • 4
  • 29
  • 46

7 Answers7

8

Programmers (even Java gurus) disagree on this.

Josh Bloch, who designed the Java Collections library, java.Math, assert, and is chief java architect at Google (or was before they hired Gosling) has a section of his book "Effective Java" devoted to this issue. I go with what he has to say:

Item 17: Design and document for inheritance or else prohibit it

He points out that subclassing classes that were not designed for it often leads to disaster.

Furthermore, designing for inheritance is expensive.

  1. It puts major limits on what your class can do
  2. You have to write more documentation so that sub class authors know how public methods are used internally by the class
  3. You must test it. This requires testing writing subclasses

You can always change your mind and make something non-final. You cant make something final that use to be not final.

Read "Effective Java" it makes this argument much more compellingly. It will also make you a better programmer.

Mason Bryant
  • 1,372
  • 14
  • 23
Philip JF
  • 28,199
  • 5
  • 70
  • 77
7

It is a good habit. Changing a final class to nonfinal should not break any code. Changing a nonfinal class to final may break some code.

emory
  • 10,725
  • 2
  • 30
  • 58
  • Unless you're writing API code, and the API user can't modify your source code. – Steve Kuo Aug 02 '11 at 00:13
  • 1
    @Steve Inheritance is over-rated. http://java.dzone.com/articles/inheritance-overrated-needed. The API user should be using composition. – emory Aug 02 '11 at 00:40
  • From Effective Java "Design and document for inheritance or else prohibit it" – emory Aug 02 '11 at 00:42
7

I'm going to say bad habit, for the following reasons:

  • You have not specified any particular need for the class to be final.
  • You are violating the open/closed principle. Classes should be open for extension, but closed for modification.
  • Finalized classes can be difficult to test with mocking frameworks.

For example:

public static void main(String[] args) {
    final Fruit mockFruit = Mockito.mock(Fruit.class);
}

private static final class Fruit {

}

...will yield...

Exception in thread "main" org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class org.foo.Foo$Fruit
Mockito cannot mock/spy following:
  - final classes
  - anonymous classes
  - primitive types

Of course, there are valid scenarios for finalizing classes. For example, your class is immutable.

hoipolloi
  • 7,984
  • 2
  • 27
  • 28
  • I think you shouldn't be mocking implementation classes. Only classes designed for inheritance. It doesn't make sense to tie your code to a specific implementation if you can test it with a mock. – Philip JF Aug 02 '11 at 02:16
  • also extension is not the same thing as subclassing. Every public class will be useable in a composition based way, but "inheritance violated encapsulation" because if you override a method it can change the behavior of other methods, so you have to design for inheritance. See http://stackoverflow.com/questions/657987/open-closed-principle-and-java-final-modifier – Philip JF Aug 02 '11 at 02:22
5

I would say it's a bad habit, because it means you're not thinking through the decision. The point of not making things final is that you can subclass and make changes without changing the original code. You're breaking this.

Scott C Wilson
  • 19,102
  • 10
  • 61
  • 83
  • What do you mean by "you're not thinking through the decision?" – Martin Tuskevicius Aug 02 '11 at 00:07
  • Exactly what I said. You described it as a habit, which means you're not making a specific, conscious decision that this class should never be overridden. – Scott C Wilson Aug 02 '11 at 00:38
  • But, not marking things final is also making a decision. The difference is that if it is final, you dont need to test/document the behavior when subclassing. – Philip JF Aug 02 '11 at 11:04
2

Your question does not have a precise answer. It depends what is the purpose of the classes you are writing. Some should be inherently final while others shouldn't, except you want explicitly to forbid subclassing.

If you are programming just by yourself, then I don't think this would make any difference, you would remove the final modifier everytime you know or you need to subclass something.

In conclusion final modifier for a class it's usually a hint to someone else about how your class should be used, not a real good/bad habit.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • It is important to add, that unnecessary "final" modifier on a class can make lifes of users of your code quite difficult. From a security standpoint, I read "final" on nested classes has no effect in the byte-code emitted. – Gabriel Ščerbák Aug 02 '11 at 00:01
  • Even if you are programming 'just by yourself', you could make your life very hard when unit-testing non-trivial code. – hoipolloi Aug 02 '11 at 00:33
0

It has no effect with HotSpot, but I am unsure about other run time systems. I never use it, because it seems to be useless. Whereas final in a variable (that also has no effect in HotSpot) can prevent you from changing a value you don't want to, you really don't have the same worries with a class.

It used to matter in HotSpot, though. And it may matter for something like Android and Dalvik.

JasonN
  • 1,339
  • 1
  • 15
  • 27
0

In general this is not a good idea. If the classes are limited to your project it is okay to do this. When you see the need to extend some of the classes he can always make them non-final.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186