8

I'm trying to put thing together in the definition of "immutability".

Item (3) here is saying, as one of the rules for creating immutable objects,

Dont allow subclasses to override methods. The simplest way to do this is to declare the class as final. ...

Overridden methods run on instances of subclasse(s). And, from what i know of, an immutable class is one of which the objects are "carved" in memory once they are instantiated-- none of its members and thus the object can't be changed.

Putting these together-- does the definition of "immutable" apply to classes as well as the objects? By finalizing the methods, I'm preventing its methods from being overridden whenever the class is extended. I don't see how finalizing the methods of an immutable class further add on making its objects immutable.

7 Answers 7

7

If you're documenting your class as immutable, users of this class can safely assume that any instance of this class is immutable.

The problem is that if you allow your class to be subclassed, nothing forbids a subclass to add mutable state and methods, or even to override methods and make them mutate this new state. So the assumption made by the users of the class falls apart. Making the class final makes that impossible.

Sign up to request clarification or add additional context in comments.

5 Comments

and how is this answering what i'm asking.
Well, you cited an excerpt of the documentation telling that immutable classes should be final. I'm explaining why. The documentation doesn't tell to make methods final. It's redundant to make them final if the class is final. So, if you're asking "why should I make methods final?", my answer is, as the documentation says: don't. Make your class final.
What you describe is commonly expressed wisdom, but I don't entirely agree with it. It's certainly true that a subclass of a class whose contract specifies that it is immutable might violate that contract, but the same would be true of any contract of any inheritable class. There are many situations where there's no logical reason for an immutable class to allow subclasses (though the same is true for all sorts of classes--not just immutable ones), but there are also many situations where subclassing would be reasonable and useful (for immutable classes as well as mutable ones).
@supercat: I'm not saying that all classes should be immutable. But if you want to use the tool that is immutability to make your concurrrent code rock solid and easier to understand and maintain, then you'd better make sure that the application doesn't fall apart because a developer created a mutable subclass without realizing the implications it might have.
@JBNizet: If there's no reason for an immutable class to allow subclassing, it's probably good to seal it. On the other hand, there are other situations where inheritance is appropriate, such as an ImmutableShape class. Inheritance and inheritability should be used where they make sense, and not where they don't, whether a class is mutable or not. Incidentally, I wish people would only use "immutable" when they really mean immutable, and "read-only" when they actually mean "read-only". They're fundamentally different concepts.
1

I don't see how finalizing the methods of an immutable class further add on making its objects immutable.

If a class is final, making its methods final is redundant; since nothing can derive from the class, nothing can override the methods whether or not they are declared final. Provided the class you've defined is immutable, if it's final, there can't be any subclasses that aren't immutable (because there can't be any subclasses at all).

Comments

1

I suppose that if the objects of a class are immutable, then you can say that the class is immutable too. String objects are immutable, so you could say that the String class is immutable.

When you make your methods final, you prevent some unknown subclass from doing the following:

@Override public void yourMethod() { doSomeMutableThing(); } 

It prevents a subclass from using inheritance and polymorphism to mutate (change) the data in your class. It also prevents a subclass from introducing some state of its own, which could be mutable.

Immutability isn't something you can just declare; you must enforce it using several techniques built-in to the Java language. Making your methods final is one of them.

3 Comments

i don't need to make all the methods final to stop some members being changed. item (1) on the same page explains.
@Roam True. See my edit. It's also possible for a subclass to contribute its own mutable data and mutator methods to the class.
The term "immutable class" is generally referred to a class whose objects cannot be mutated, even by code which has a reference to them. Another useful concept, for which I'm unaware of any standard term, is what I would call an "immutable instance", which is to say a particular object instance can be guaranteed to never change, because even if it would allow code holding a reference to mutate it, no code which would mutate it will ever acquire a reference. The backing stores of String objects fit that description.
1

does the definition of "immutable" apply to classes as well as the objects?

Seeing as how a class is the blueprint of an object, yes?

The more important distinction to make here is that -- Adding final everywhere does NOT make your class / object immutable. at all.

Consider this:

final class Foobar { /* * in this context, final just means you can't rebind the variable. * it doesn't make the list immutable. */ final List<String> notReallyImmutableList; Foobar() { notReallyImmutableList = new ArrayList<String>(); } final void addToList(String string) { notReallyImmutableList.add(string); // totally legit if you have an instance of Foobar } } 

1 Comment

@Roam No, no i didn't. I tried to give a counterexample showing that final does not imply immutability.
1

Immutable means that the object CANNOT change. So the standard String object in Java is immutable - you can pass it around, you can hold as many references as you like to it but you cannot modify it. If you wanted to modify a string you would use a StringBuilder (or StringBuffer) to append or modify it.

But String is an intrinsic system supplied class so its immutability can be taken at face value. If you wished to create an immutable class then you can only do so by only providing methods which are guaranteed not to modify its internal state. Since a class is usually overridable it is conceivable that a piece of code might subclass your class just to modify the internal state.

Therefore:

  1. Make all your fields internal private. They should be tagged final too since they should only be set from the constructor.
  2. Do NOT return any fields which are themselves are objects unless they too are immutable.
  3. Mark the object final and all methods final
  4. Do NOT provide any methods which can modify the internal state
  5. Operations like clone(), add(), subtract(), split(), diff(), combine() etc. which spit out new objects should not reference the existing object or its fields to be on the safe side. Use deep copy to ensure they are thread safe.
  6. If your object returns collections of other objects then use methods like Collections.unmodifiableList(), unmodifiableMap() etc. to stop people abusing those collections.
  7. Likewise if the object or any field implements interfaces designed for read/write operations, then throw exceptions in the implementation of any write operation.

Immutability is a good quality for objects (especially those where ownership can be an issue, or concurrency is) but the downside is you may construct a lot of throwaway objects and therefore they can be inefficient. So it's a tradeoff and it depends what you need the objects for whether it is worth it.

Comments

1

There are substantial differences in the appliance of the final keyword.

Appliance...

  • ... to classes prohibits sub-classing (and thus, method overrides aswell)
  • ... to methods prohibits method overrides
  • ... to instance variables ensures immutability of these fields and thus also for whole objects, if specified for all, since final variables can just be written once, on construction.

Docs:

Comments

0

Objects define behavior and state. immutability refers to an object that once created will not change its internal state.

this makes easier to work with threads, among other advantages, here is an example from guava of an immutable list. cant post links since im new... http://google-collections.googlecode .com /svn/trunk/javadoc/com/google/common/collect/ImmutableList.html

so to answer your question, finalizing methods limits inheritance, but not immutability.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.