A similar question to this is asked in the StackOverflow thread immutable class should be final?: "So why is immutability a good reason for making a class final?" In this blog post, I look a little more deeply into this issue.

By declaring immutable classes final, we impose a guarantee that malicious subclasses capable of changing the state of the object and violating assumptions that clients often make regarding immutability, are not a concern.

In Immutable Objects in Java, the four authors (Haack, Poll, Schafer, and Schubert) include a section on "enforcing immutability." In this section they maintain that classes which extend immutable classes must also themselves be immutable. The authors suggest that making the immutable class final would be one way to deal with a situation in which "malicious code may try to subclass an immutable class" and "masquerade" as its parent type,

In Mutable and Immutable Objects, David O'Meara specifies that there are two approaches for ensuring methods are not overridden in a class designed to be immutable. He differentiates between strong immutability (class is made final) and weak immutability (methods are individually and explicitly declared final rather than declaring class final). In O'Meara's words, "The preferred way is to make the class final" (strong immutability).

With the above background details in mind, it's time to move on to some code examples.

The following Fraction class has some traits of immutability (such as its fields being final and private):

Because the parent Fraction class is not final and its method are not final, the RenegadeFraction class is able to override its methods and return nonsensical results. Note that even if we made the main methods final, the constructor of RenegadeFraction could still intentionally or accidentally swap the constructor arguments passed to its parent class.

This example also shows a misbehaving toString() implementation in the subclass. If we extend the Fraction class and mark the methods we don't want overridden with final, there could be confusing issues surrounding "other" methods like toString(). Do we want to make toString() final or allow the child class to potentially misrepresent its (and its parent's) real contents?

The next code listing demonstrates how a child class can misrepresent its parents to clients. The main code here believes it is dealing with Fraction class and may even make some assumptions based on that. The actual instance passed to the client is the RenegadeFraction resulting from intentional abuse or from careless development.

DemonstrationMain.java

package dustin.examples;

import java.math.BigDecimal;import static java.lang.System.out;

/** * Demonstrate how allowing an immutable class to be extended can reduce * immutability, at least from the perspective of its behavior. */public class DemonstrationMain{ /** * Enumeration representing type of fraction to help in readability of output. * * This differentiates between the original Fraction and the extending class * RenegadeFraction. */ public enum FractionType { FRACTION("Fraction"), RENEGADE_FRACTION("Renegade");

printExternalDivisionResults( new RenegadeBigDecimal(fraction.getNumerator()), new RenegadeBigDecimal(fraction.getDenominator())); printExternalDivisionResults( new RenegadeBigDecimal(renegadeFraction.getNumerator()), new RenegadeBigDecimal(renegadeFraction.getDenominator())); }}

When the above demonstration class is executed, its output appears as shown below:

The output shown above demonstrates how a subclass can misrepresent its parent's advertised behavior. This can happen anytime implementation inheritance is involved, but it is more insidious when we have reason to believe the class involved is immutable. We could mark the methods as final to reduce much of this, but the constructor still has issues. Furthermore, marking all the parent class's methods as final rather than simply marking the entire class as final has some drawbacks. These include the potential conundrum about how to handle methods (such as toString()) that really should not be final and the risk of new methods being added to the parent class without the developer remembering or knowing to mark them as final.

In the DemonstrationMain class, I also made use of a custom class called RenegadeBigDecimal. The purpose of this class is to demonstrate the abuse of a subclass of BigDecimal. The code listing for RenegadeBigDecimal is shown next.

This last example shows how easy it is to abuse BigDecimal. Because the divide method was overridden to return itself, it is obvious that neither the BigDecimal class nor its method divide were designated as final. Even if the divide method would have been made final, the constructor could still have implemented bad intent and any client code thinking it was a BigDecimal would pay the consequences.

Trade-offs and Drawbacks of final Immutable Classes

There may be times when the ability to override a "largely immutable" or "mostly immutable" class is more important than having a "completely immutable" or "strongly immutable" class. Software design and development is full of trade-offs and this is just another one of those. The benefits of different degrees of mutability can be weighed against the costs. I believe it is no coincidence that Joshua Bloch changed the title of his Effective Java item on immutable objects from "Favor Immutability" in Edition 1 to "Minimize Mutability" in Edition 2. I think this is most readily done by starting with a class that is completely or strongly immutable and only relaxing its mutability in different ways when justified by the benefits of doing so.

Again, at least in my mind, it is no coincidence that the creators of the recently announced Noop project have stated that they wish to encourage immutability and that they wish to discourage implementation inheritance. I think in many of the cases in which implementation inheritance might be desired, it might be better to simply use composition to share common, immutable data and behaviors between two highly related, possibly immutable, classes. That advice doesn't sound particularly different than what many others have suggested before in terms of all classes, including mutable classes.

Conclusion

The safest way to make a class "strongly immutable" is to designate the entire class as final. Doing so ensures that no mistakes will be made in creating new methods in the future in the immutable class that are not marked final and can be carelessly or maliciously overridden. The final keyword applied at class level also prevents subclasses from "masquerading" as their immutable parent with very different behavior than that expected for the "immutable" parent class.