QCon London ‘09 Long stand up meetings
Mar 17

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.

Every now and then I still do some Java coding. And I actually like it. I spent several years of my career developing primarily in Java and am very keen about the language.

I’ve been a fierce defender of it these days, specially with the wave of popularity of other languages such as Ruby and Groovy. But I must say that for the 1st time - actually the 2nd - I got pissed off at Java.

The reason? Final classes!

How arrogant of someone to say: “And from now on you shall not subclass my classes!”

Er…. Why?!?! I’m yet to find a good reason in favor of it. But I can share 2 that made me be completely against it. - I never actually liked it but it just didn’t bother me that much in the past.

The first one happened while I was adding PostgreSQL XML support to Hibernate. The basic idea is that the XML data type should behave mostly as a string, with the exception of the saving and loading operations.

The thing is, the String data type in Hibernate is declared final. So you cannot share behavior unless you copy and paste it. How smart.

And the second is in the testing area. We all love testing. And we all love mocking external dependencies so we can test our code in isolation and fast. Well, I hope your code doesn’t depend on the URL class then.

It is declared final so you just can’t mock it. Mocking frameworks like easyMock use subclassing to create your dependencies mock objects and obviously it doesn’t work here.

Yeah yeah, of course you can refactor your code so it depends on an interface/class that wraps your URL class and then you can switch implementations. But just how stupid is that? Programming to interfaces makes sense, but not everywhere. Specially not when you’re using a low level class like this one.

So please, software developers, architects and the like, design your systems for extensibility and stop being presumptuous.

P.S.: There is a testing framework called jMockit which uses instrumentation (Java 5+) to redefine methods in runtime so you can mock final classes. It works, but should we really be playing that much with the java class loader just so we can “easily” test our code?

Related Posts

11 Responses to “Final classes are evil”

  1. My solution: Forget Java, it is a dead language haha.

    The future is ruby, the future is here, the future is now.

    Long live ruby!!

  2. Haha
    Man you know how much I like Ruby. But it’s not like it’s the solution for everything! :p

  3. raul says:

    Design a class to be proper inheritable is a pain, beside the public interface you have to publish the internal one, how is going to interact the internal methods, how the internal variable works, the internal caches. All in all inheritance is a bad OOP practice and all the design patterns are develop to avoid it.
    I think the problem is not the final class but that they were not coding against an interface

  4. Hi Raul! Tks for stopping by!

    I totally agree that, in Java, not coding to an interface is a problem. I’m 100% with you there.

    My problem with making a class final is that it just doesn’t make sense. Or at least I haven’t found someone to make me see it.

    Probably when Java was first conceived it made a lot of sense. - But so did null references in the past right? :)

  5. ESP says:

    Immutability is a great thing. Why make a class final ? To make it immutable.

    Take a look on item 15 “Minimize mutability” from Joshua Bloch’s Effective Java.

  6. Hello ESP! Tks for stopping by!

    I have to disagree with you. Only by marking your class final, you don’t ensure it’s immutable. It’s useless to declare it final if you provide mutators (e.g. setters).

    By immutable Joshua meant you cannot change state, which means you’re talking about instances of that class. That can be achieved without marking the class itself final.

    He does mention marking the class as final to prevent “malicious or careless code”. Which has to do with the item 17: Document for inheritance or mark it final. Which I agree.

    But I go further and say that if you mark it final - because you didn’t want design it for inheritance, code it against an interface. It will make all our lives easier. :)

  7. Radoslaw Maruszewski says:

    I think articles like this are very harmful. Beginner programmers read it and start to believe that they should not use “final” at all, or use it with great caution. The truth is something quite opposite: use the “final” keyword freely, and if you don’t know if you class should be “final” or not, err on the side of “final” (in fact, all the class members and classes should be “final” by default, and there should be a keyword to change this behavior, not the other way round).

    There are many valid reasons for this:

    1. If class is not designed for extension, it’s easy to break LSP and write really bad and vulnerable code. Like extending String class by XML class, when somebody just wants to inherit part of the String behavior - even is XML is not really a String. From now on any change on String class (like adding, removing or changing a method) may break the XML code, and may cause wicked errors.

    2. Like ESP said, the only way to assure that your immutable class will actually stay immutable, is to add the “final” keyword. Otherwise somebody may extend it, overwrite methods returning immutable data (like copy of class member), or directly change the class members.

    3. If you leave your class open for inheritance (no “final” method), you should ensure if it will properly work with serialization, cloning, checking equality, and that the inherited classes will behave properly in the multi-thread environment. That’s what Bloch means by “design for inheritance”.

    Also be careful when using “final” for a class that doesn’t implement an interface, as you don’t leave any possibility of mocking/replacing it (so that’s the only statement from this article I agree with ;-)).

  8. Hello Radoslaw!

    I definitely didn’t intend it to be harmful. After all, this are only my findings, experiences and opinions.

    Back to the post, actually the point you agree with is the most important I was trying to make. :) No argument there.

    Regarding designing for inheritance, yes I agree it’s hard. But in such case, the developer should be coding to an interface, as you stated yourself. And I guess that’s where the flaw is.

    Specially in the past when testing wasn’t such a big issue as it is today…not to mention we didn’t have the strategies for mocking, stubbing and etc… that we do now.

    Tks for keeping the discussion interesting.

  9. Rogério Liesenfeld says:

    I think you are making several mistakes:
    1) JMockit does not rely on custom class loaders. Anyway, I don’t see why a user should care which mechanisms the tool uses internally to do the job. What matters is how easy it is to use, and how clean the resulting test code is.
    2) “Design for extensibility” means that I should either explicitly design and document a class for inheritance and other extension mechanisms, or declare it or some of its methods final. Simply making all classes non-final by default is not “designing for extensibility”. BTW, I make most of the classes/methods I create final, and hardly ever had to remove the “final” modifier later.
    3) I think you misunderstand what “program to an interface, not an implementation” (from the GoF book) means. It’s not about mindlessly creating separate abstractions/interfaces for every class, as you seem to imply. “Coding to an interface” only means that you should declare variables/fields/parameters with the abstract/interface type, not with the separate class/implementation type (for example, with List and ArrayList, declare “List lst”, not “ArrayList lst”).

  10. Hi Rogério!
    Good to know the title brought so much attention to the topic. It’s purposely appelative. :)
    Now a few comments on your considerations:
    1) I didn’t mention custom class loaders, as far as I understood it, jmockit mocks final classes trough the use of instrumentation. I consider it being an advanced feature from the class loader - but please correct me if I’m wrong - used to circumvent the lack of flexibility on final classes. It does work, but last time I tried it, it wasn’t so simple to use.

    2) If you keep in mind that inheritance is, overall, a bad OOP practice, marking a class as final doesn’t make much sense in most systems. And that’s one thing I don’t like about java. Many of it’s keywords and patterns are there to keep people from creating malicious/careless code. I think this is a social problem rather than a technical issue.

    3) As you stated yourself, you should use List, instead of an ArrayList. The same should be true with most, if not all, dependencies you have. The problem with classes that are final and do not provide an interface is that you have to create this interface yourself - to wrap the dependency. Otherwise the coupling between both will be high.

    And lastly but not least, the overall point I was trying to make when I wrote this article was that final classes are evil for testing. Perhaps I should have included that in the title, but on the other hand, it served to keep the discussion interesting. :)

    Thanks for stopping by.

  11. [...] said final classes are evil and that post got some attention with interesting comments. Maybe because of the title and the tone [...]

Leave a Reply

preload preload preload