• Post Reply Bookmark Topic Watch Topic
  • New Topic

Immutable objects  RSS feed

 
Shital Kapadia
Ranch Hand
Posts: 34
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I understand what do you mean by the statement that a 'String is immutable', however, I would like to understand as to why this class is Immutable and if someone can pls help me understand as to when and how can you decide that this class needs to be designed as an Immutable class.
Thanks for all your help,
Shital Kapadia
 
Greg Charles
Sheriff
Posts: 3015
12
Firefox Browser IntelliJ IDE Java Mac Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's immutable basically because it has no "set" methods. That is, once the series of characters has been set that make up the String, they cannot be changed. There are many methods that take a substring, or convert characters to uppercase, but they alway create a brand new String with a new sequence of characters. The original String object remains unchanged.
To create your own immutable class, you need to write a constructor (or constructors) that establish the original state, and then not provide any methods to change the state. That's it!
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Note that String has many methods which seem to change the contents of the String - but if you look closely, they always create a new String with different contents - they never change the original. E.g.:

The final print of s shows that it hasn't really been altered. Instead, many new strings were created.
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
... and if someone can pls help me understand as to when and how can you decide that this class needs to be designed as an Immutable class.
Basically, there are a some tests to determine when a class should be immutable. First, the class is primarily a value representation of something, for example a String, an Integer, a Double, a Complex, etc. Second, object identity is unimportant, that is you don't want to distinguish between two instances with identical state (values). Finally the class displays little behavior aside from retrieving the value or using its internal state for some purpose. These factors are not absoultes and there may be other criteria in some cases that you would want a class to be immuatable.

To create your own immutable class, you need to write a constructor (or constructors) that establish the original state, and then not provide any methods to change the state. That's it!

Not quite Greg. you should also decide whether the class will be strongly immutable by declaring the class final, or weakly immutable by declaring the methods final. Also, you must protect all state which involves an object reference by making a deep copy of the referred object and returning the copy in a getter for that state.
Take 10 minutes to read this excellent article by David O'Meara from the JavaRanch April Newsletter.
 
Greg Charles
Sheriff
Posts: 3015
12
Firefox Browser IntelliJ IDE Java Mac Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Michael Morris:

Not quite Greg. You should also decide whether the class will be strongly immutable by declaring the class final, or weakly immutable by declaring the methods final. Also, you must protect all state which involves an object reference by making a deep copy of the referred object and returning the copy in a getter for that state.


That's a good point about needing to make a deep copy of object members, unless of course, the object members are also immutable. However, I don't see how making either class or methods final makes any difference. Presumably your member variables are private, so subclassing isn't going to allow them to be set. Overriding methods that don't change the state also wouldn't allow the state to change. I suppose the subclass could add state, which could then be mutable, but so what? When I create an immutable class, I'm not guaranteeing that every subclass of it will be immutable ... or am I? I'll take a look at that article when I get a chance.
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
However, I don't see how making either class or methods final makes any difference. Presumably your member variables are private, so subclassing isn't going to allow them to be set. Overriding methods that don't change the state also wouldn't allow the state to change. I suppose the subclass could add state, which could then be mutable, but so what? When I create an immutable class, I'm not guaranteeing that every subclass of it will be immutable ... or am I? I'll take a look at that article when I get a chance.
Let's assume that java.lang.Integer were not declared as public final class Integer. What then would prevent me from doing this:

Now, because of polymorphism, any context expecting an Integer will accept my MutableInteger, so I have in effect thwarted the efforts of the original class designer to provide an object whose value can't change.
 
Thomas Paul
mister krabs
Ranch Hand
Posts: 13974
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Michael Morris:
Now, because of polymorphism, any context expecting an Integer will accept my MutableInteger, so I have in effect thwarted the efforts of the original class designer to provide an object whose value can't change.

Is that always a bad thing? Maybe I have a bunch of methods that will only take an Integer but I really need to make it mutable. Or even better, the Integer part is only one small part of a much bigger class that does a bunch of other stuff. Your solution would nicely solve my problem.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is that always a bad thing?
Not always - that's why we distinguish between strong and weak immutability. Sometimes the latter is really what you want. But it's risky - you have to make sure that no one else is using the class under the illusion that they're dealing with an immutable object. I might be writing a component in which multiple threads are accessing a HashMap with String keys and Integer values. I synchronize access to the shared HashMap, but since String and Integer are immutable I don't synchronize the code that works with these, and I may pass references to these objects to or from outside applications, knowing that it doesn't matter what those applications do with the references. If I accept a String reference and it turns out it's really a MutableString defined by someone else and being manipulated by other threads I know nothing about, there could be all sorts of complications. That's one reason why most immutable classes are made final - to ensure that they're really immutable.
 
Greg Charles
Sheriff
Posts: 3015
12
Firefox Browser IntelliJ IDE Java Mac Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The article was vague on why finality is a good idea, but Michael's example is a good one. If I've got an immutable Widget class and a mutable SubWidget, I still want anyone using a Widget reference to have an illusion of immutability, even if the object being referred to is a SubWidget. For example, if Widget defines a method getName(), that method should always return the same result for a given object, no matter when it is called. If all of Widget's methods are final, then the fact that SubWidget adds behavior won't affect anyone using a Widget reference. Making the class Widget final, of course, means there is no SubWidget class at all.
That's cool. I've learned something! Thanks to all!
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If all of Widget's methods are final, then the fact that SubWidget adds behavior won't affect anyone using a Widget reference. Making the class Widget final, of course, means there is no SubWidget class at all.
Right. It's up to the designer of the immutable class to determine whether he wants the class to be strongly immutable or weakly immutable so as to allow added behavior in subclasses without breaking the immutablility of the parent class. Personally, I think that if you have a strongly immutable class you should have only private constructors and use static factory methods to get instances.
 
Greg Charles
Sheriff
Posts: 3015
12
Firefox Browser IntelliJ IDE Java Mac Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Michael Morris:
I think that if you have a strongly immutable class you should have only private constructors and use static factory methods to get instances.

Why do you think that? String, and all of the wrapper classes, including Integer, are strongly immutable, and yet have constructors. They seem to work fine. Should I be worried?
 
Michael Morris
Ranch Hand
Posts: 3451
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
They seem to work fine. Should I be worried?
No, they are fine. My statement was overly broad. Many times using private constructors and factory methods make the code clearer if you are talking about a value object that has a lot of state and the private constructors further lock down the class. You can even pool instances for efficiency, if you are going to have a lot of them floating around. You can return inner subclasses (of course that precludes the use of final in the class definition) from your factoy and no one is the wiser. The bottom line is you now have complete control of the class' immutability.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!