• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Immutable in Java - Queries in Implementation

 
Ranch Hand
Posts: 143
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi All,

Below are the steps to be followed to make an Object as IMMUTABLE:

i. Don't provide any setter method for fields/properties.

ii. Mark all the fields as private.

iii. Mark all the methods as final so that methods can't be overridden.

iv. Mark the class as final so that class can't be subclassed.

Now, I have the following queries:

i. If the class is marked as final, then why do we need to mark the methods as final since anyways we can't subclass this class.

ii. If the fields are already private, then what is the use of making the methods as final since anyways we can't access the properties in subclasses.
 
Bartender
Posts: 3323
86
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You should also include in that list "Don't provide any method that changes the state of the object"
 
Bartender
Posts: 4179
22
IntelliJ IDE Python Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Vaibhav G Garg wrote:i. If the class is marked as final, then why do we need to mark the methods as final since anyways we can't subclass this class.


It is redundant to label the class as final and its methods as final. Labeling the methods as final has no effect, since all methods in a final class are effectively final. It does't hurt though. This is from the JLS:

JLS Chap8 Sec4 wrote:A private method and all methods declared immediately within a final class (ยง8.1.1.2) behave as if they are final, since it is impossible to override them.

JLS 8.4.3.3

Note that the opposite is not true. You can't make the methods all final and not the class.


Vaibhav G Garg wrote:ii. If the fields are already private, then what is the use of making the methods as final since anyways we can't access the properties in subclasses.


If the class was not final, and so its methods were not final, a subclass could use a member variable of its own and override the getter methods to use this different variable the subclass does have access to. The subclass could then allow state change that the super class could not control. Since, at that point, not all instances of the super class are immutable then you can't assume any are.
 
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Steve Luke wrote:Note that the opposite is not true. You can't make the methods all final and not the class.



Well, you can. It just won't have the same effect.


a subclass could use a member variable of its own and override the getter methods to use this different variable the subclass does have access to.



Heck, it wouldn't even need a member variable. Just returning a constant, or super.getFoo() + 1 or the current time or a random value would do it.
 
Vaibhav G Garg
Ranch Hand
Posts: 143
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Steve and Jeff.

I still have the following query:

1. If the variable is marked as private and final, then I assume that we can't change the value of a variable, so, why do we need to mark the method as final?
 
Ranch Hand
Posts: 199
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

My thoughts on the topic

i. If the class is marked as final, then why do we need to mark the methods as final since anyways we can't subclass this class.


I think that is not required but you get a better chance that the compiler transforms the method to native code (HotSpot).

ii. If the fields are already private, then what is the use of making the methods as final since anyways we can't access the properties in subclasses.


You still can have access to private methods through reflection.


Best regards,
 
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Those steps are necessary. but I can still write a class which follows all those instructions and whose state is mutable.
I shall give you a few hours to work out what additional action must be taken in order to make the class immutable.

And, by the way: please always tell us where such material comes from.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Vaibhav G Garg wrote:1. If the variable is marked as private and final, then I assume that we can't change the value of a variable, so, why do we need to mark the method as final?



If the class is final, then the method doesn't have to be final. But if neither one is final, then a subclass can override the method to return whatever it wants.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Carles Gasques wrote:

ii. If the fields are already private, then what is the use of making the methods as final since anyways we can't access the properties in subclasses.


You still can have access to private methods through reflection.



We don't even need to do that. We don't need to access the fields to violate immutability. If a subclass can exist and can override a method that reflects the object's state, then all that subclass has to do to break immutability is return a different value from its method than what the parent returns. Even though the internal state of the object may not have changed, to a user of the class, it appears that it has.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There is still another pitfall which I haven't mentioned.
 
Vaibhav G Garg
Ranch Hand
Posts: 143
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:There is still another pitfall which I haven't mentioned.



Thanks Jeff and Campbell.

Hi Campbell, can you please highlight that pitfall also.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sorry for the delay in replying. Can you see the pitfall?
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Have you found the pitfall yet?
 
Ranch Hand
Posts: 163
Eclipse IDE Tomcat Server Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I hope it's alright if I answer.

The pitfall is the reference to the numbers array in the constructor and getNumbers(). The array is not copied, so the reference can be manipulated
from outside the scope of the Immutable class.

 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Agree. You need to take a defensive copy of any mutable reference types, which includes arrays, whenever they go into your class (constructor) or come out (getXXX methods).
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Agree. You need to take a defensive copy of any mutable reference types, which includes arrays, whenever they go into your class (constructor) or come out (getXXX methods).



So the rules in the OP should have included:

v. If any mutable fields are exposed to the outside world, their contents must be copied to a new object first, and that object, not the field, must be what's exposed.

with the corollary:

vi. If any mutable objects are accepted as arguments for establishing the object's state, their contents must be copied toa new object first, and a reference to that new object must be what's stored as the field.


Also note that both of those rules include recursive references to immutability, with the implication that any mutable objects passed in or out must be deep cloned over all their own mutable fields.
 
Master Rancher
Posts: 4806
72
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jeff Verdegan wrote:So the rules in the OP should have included:

v. If any mutable fields are exposed to the outside world, their contents must be copied to a new object first, and that object, not the field, must be what's exposed.


I think "mutable field" is misleading here; it sounds to me like it could refer to any non-final field. I think you mean: a field which references a mutable type. Such as an array or a StringBuilder, but not a String.

There's another loophole in the rules given so far: it's not thread-safe. If the fields are not made final, then it's possible for some threads to see fields in their uninitialized values.

If you make all fields final, rule ii becomes irrelevant. Making fields private is considered a good principle for OO programming: hide your data, favor encapsulation. But it's unnecessary for making your object immutable. Provided the field is final.

If you don't want to make the fields final, well there are other ways to make the design thread-safe (effective immutability with safe publication, or force a memory barrier before every read) but they are hard to comprehend or explain. Making fields final should be considered the preferred way.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:

Jeff Verdegan wrote:So the rules in the OP should have included:

v. If any mutable fields are exposed to the outside world, their contents must be copied to a new object first, and that object, not the field, must be what's exposed.


I think "mutable field" is misleading here; it sounds to me like it could refer to any non-final field. I think you mean: a field which references a mutable type. Such as an array or a StringBuilder, but not a String.



Yeah, I got lazy. Thanks for clarifying.

If you make all fields final, rule ii becomes irrelevant.



As long as that rule is applied recursively to all fields that point to mutable objects as well, yes. Which it would be if it's one of our rules of immutability, and that definition of immutability is applied recursively to all fields.

Fun stuff!

I've often wished there was an immutable keyword or something in Java. I suppose it could be done with annotations. There are times when it would be nice to look at either a class or a particular instance of a class, and know (without having to dig into its source and the source of all its fields) that it will be immutable.
 
Mike Simmons
Master Rancher
Posts: 4806
72
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jeff Verdegan wrote:I've often wished there was an immutable keyword or something in Java. I suppose it could be done with annotations. There are times when it would be nice to look at either a class or a particular instance of a class, and know (without having to dig into its source and the source of all its fields) that it will be immutable.


I think this is long overdue. There was one in JSR-305, but that's dormant. @Immutable is used as an example in JSR-308, which is supposedly coming in Java 8. But I don't know if @Immutable itself will be included, or if that's deferred to later. The Checker framework has an Immutable, but that's checkers.igj.quals.Immutable, so not quite mainstream, I'd say. You can get a JSR 305 jar file that has javax.annotation.concurrent.Immutable, which sounds relatively official, and is used by FindBugs. I'm not sure why that project is listed as dormant now.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic