tags:

views:

1073

answers:

6

Hi,

It says in this article that "Making a class final because it is immutable is a good reason to do so". I'm a bit puzzled by this....I understand that immutability is a good thing from the POV of thread-safety and simplicity, but it seems that these concerns are somewhat orthogonal to extensibility. So why is immutability a good reason for making a class final?

Cheers, Don

+3  A: 

Because if the class is final you can't extend it and make it mutable.

Even if you make the fields final, that only means you cannot reassign the reference, it does not mean you cannot change the object that is referred to.

I don't see a lot of use in a design for an immutable class that also should be extended, so final helps keep the immutability intact.

cynicalman
But you might want to extend an immutable class in order to add additional immutbale properties.
Don
"Because if the class is final you can't extend it and make it mutable"But you can't extend a non-final immutable class and make it mutable, you can only make the subclass mutable
Don
As a caller, you don't know whether you're using the immutable class or its mutable subclass - unless you happened to call the constructor directly. That's polymorphism.
slim
+3  A: 

Following the Liskov Substitution Principle a subclass can extend but never redefine the contract of its parent. If the base class is immutable then its hard to find examples of where its functionality could be usefully extended without breaking the contract.

Note that it is possible in principle to extend an immutable class and change the base fields e.g. if the base class contains a reference to an array the elements within the array cannot be declared final. Obviously the semantics of methods can also be changed via overriding.

I suppose you could declare all the fields as private and all the methods as final, but then what would be the use of inheriting?

Garth Gilmour
Say you have an immutable Shape class, which has an area property. You might want to create a Circle subclass which has additional properties such as radius. These new properties might themselves be immutable, thus preserving the immutability property of the parent. What's wrong with that?
Don
I don't think there's anything wrong with that, as long as you are the only person extending from Shape. But you would have to create precise guidelines for other developers and be confident they would follow them. So I think the argument is that 99.9% of the time its not worth the effort...
Garth Gilmour
GG's on the money. If you make a guarantee you have to keep it.
CurtainDog
+5  A: 

Mainly security I'd think. For the same reason String is final, anything that any security-related code wants to treat as immutable must be final.

Suppose you have a class defined to be immutable, call it MyUrlClass, but you don't mark it final.

Now, somebody might be tempted to write security manager code like this;

void checkUrl(MyUrlClass testurl) throws SecurityException {
    if (illegalDomains.contains(testurl.getDomain())) throw new SecurityException();
}

And here's what they'd put in their DoRequest(MyUrlClass url) method:

securitymanager.checkUrl(urltoconnect);
Socket sckt = opensocket(urltoconnect);
sendrequest(sckt);
getresponse(sckt);

But they can't do this, because you didn't make MyUrlClass final. The reason they can't do it is that if they did, code could avoid the security manager restrictions simply by overriding getDomain() to return "www.google.com" the first time it's called, and "www.evilhackers.org" the second, and passing an object of their class into DoRequest().

I have nothing against evilhackers.org, by the way, if it even exists...

In the absence of security concerns it's all about avoiding programming errors, and it is of course up to you how you do that. Subclasses have to keep their parent's contract, and immutability is just a part of the contract. But if instances of a class are supposed to be immutable, then making it final is one good way of making sure they really are all immutable (i.e. that there aren't mutable instances of subclasses kicking around, which can be used anywhere that the parent class is called for).

I don't think the article you referenced should be taken as an instruction that "all immutable classes must be final", especially if you have a positive reason to design your immutable class for inheritance. What it was saying is that protecting immutability is a valid reason for final, where imaginary performance concerns (which is what it's really talking about at that point) are not valid. Note that it gave "a complex class not designed for inheritance" as an equally valid reason. It can fairly be argued that failing to account for inheritance in your complex classes is something to avoid, just as failing to account for inheritance in your immutable classes is. But if you can't account for it, you can at least signal this fact by preventing it.

Steve Jessop
A: 

The Class is in essence only immutable if, from the outside of an instance, the internal data is unchangable by a caller.

There is no correlation between the immutable nature of the Classes content and allowing it to be extended.

_ande_turner_
That rule is too simplistic. java.lang.String has non-final fields, for instance.
Grundlefleck
@Grundlefleck: All but one in String are, and I suspect the "private int hash; // Default to 0" isn't because it is lazily initialized.. so from the outside of the class all fields are immutable anyways. As a User of the String class you shouldn't care about the internals, the point I was trying to make is that from the outside of an instance the internal data is unchangable by a caller.
_ande_turner_
"...the point I was trying to make is that from the outside of an instance the internal data is unchangable by a caller" - spot on! *This* should be your answer ;-)
Grundlefleck
A: 

Its a good idea to make a class immutable for performance reasons too. Take Integer.valueOf for example. When you call this static method it does not have to return a new Integer instance. It can return a previously created instance safe in the knowledge that when it passed you a reference to that instance last time you didn't modify it (I guess this is also good reasoning from a security reason perspective too).

I agree with the standpoint taken in Effective Java on these matters -that you should either design your classes for extensibility or make them non-extensible. If its your intention to make something extensible perhaps consider an interface or abstract class.

Also, you don't have to make the class final. You can make the constructors private.

A: 

I was asked a question at a interview, the question was:

What is the other way to make a class final if i dont want to use final keyword?

I really want to know the answer for this question! Can you please help!

rorac
Answers are not the place to ask new questions. I would suggest posting this as a new question, but it has been asked before: http://stackoverflow.com/questions/451182/stopping-inheritance-without-using-final/
finnw