9

Can we create an immutable object without having all fields final?

If possible a couple of examples would be helpful.

5
  • Using final only helps the compiler catch some errors. A class can be mutable with final field and immutable without them. However, if you have an immutable class which cannot have final fields, you have to ask why this is so... ;) Commented Sep 21, 2011 at 14:13
  • 1
    Why wouldn't you want to use final fields? Commented Sep 22, 2011 at 20:21
  • 1
    @DavidCaunt Lazy evaluation of a field, e.g. java.lang.String's hashCode. Can be useful to not have the field final, though very tricky to get right. Commented Nov 2, 2011 at 22:44
  • possible duplicate of Must all properties of an immutable object be final? Commented Jul 4, 2014 at 7:36
  • It makes it immutable but not thread safe!!! docs.oracle.com/javase/specs/jls/se7/html/… Commented Jan 13, 2017 at 8:10

7 Answers 7

7

Declare all fields private and only define getters:

public final class Private{
    private int a;
    private int b;

    public int getA(){return this.a;}
    public int getB(){return this.b;}
}

citing @Jon Skeet's comment, final class modifier is useful for:

While an instance of just Private is immutable, an instance of a subclass may well be mutable. So code receiving a reference of type Private can't rely on it being immutable without checking that it's an instance of just Private.

So if you want to be sure the instance you are referring to is immutable you should use also final class modifier.

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

4 Comments

Note that this class is not final - therefore while an instance of just Private is immutable, an instance of a subclass may well be mutable. So code receiving a reference of type Private can't rely on it being immutable without checking that it's an instance of just Private.
@Jon Skeet: yes thanks for pointing out. Mine was just a simple answer ... anyway final is the more accurate way to handle fields that are not supposed to change.
@Heisenbug "So if you need also subclass to be immutable use final class modifier." If you use final modifier, you can not create subclass, please correct the last line or make me understand
@Naroji: sorry, my answer was wrong. I tried to correct it. What Jon was pointing out is that if you have a base class reference to an object that is a subclass instance, you can't assume the subclass instance is immutable too (so you can refer something you think immutable but actually it isn't). If you want to be sure of immutability of a class, prevent it from subclassing.
6

Yes, it is - just make sure that your state is private, and nothing in your class mutates it:

public final class Foo
{
    private int x;

    public Foo(int x)
    {
        this.x = x;
    }

    public int getX()
    {
        return x;
    }
}

There's no way of mutating the state within this class, and because it's final you know that no subclasses will add mutable state.

However:

  • The assignment of non-final fields doesn't have quite the same memory visibility rules as final fields, so it might be possible to observe the object "changing" from a different thread. See section 17.5 of the JLS for more details on the guarantees for final fields.
  • If you're not planning on changing the field value, I would personally make it final to document that decision and to avoid accidentally adding a mutating method later
  • I can't remember offhand whether the JVM prevents mutating final fields via reflection; obviously any caller with sufficient privileges could make the x field accessible in the above code, and mutate it with reflection. (According to comments it can be done with final fields, but the results can be unpredictable.)

6 Comments

And what about reflection mechanism ?
For me is sometimes hard to comprehend the speed of your answers. There might by two possibilities or you are living in some parallel world were time move slower, or you have godlike speed in fingers. ;-).
@jon Skeet: "The assignment of non-final fields doesn't have quite the same memory visibility rules as final fields, so it might be possible to observe the object "changing" from a different thread". could you expand this a little bit?
@Heisenbug: Basically any assignments to final fields within constructors are guaranteed to be visible to all threads when the constructor is finished; non-final fields don't have the same guarantees. See section 17.5 of the JLS for more details.
@JonSkeet: thanks for explanation: can I edit my answer adding your comment to final class declaration? I think could be useful highlight it.
|
3

The term "immutable", when used to descrbie Java objects, should mean thread-safe immutability. If an object is immutable, it is generally understood that any thread must observe the same state.

Single thread immutability is not really interesting. If that is what really referred to, it should be fully qualified with "single thread"; a better term would be "unmodifiable".

The problem is to give an official reference to this strict usage of the term 'immutable'. I can't; it is based on how Java bigshots use the term. Whenever they say "immutable object", they are always talking about thread safe immutable objects.

The idiomatic way to implement immutable objects is to use final fields; final semantics was specifically upgraded to support immutable objects. It is a very strong guarantee; as a matter of fact, final fields is the only way; volatile fields or even synchronized block cannot prevent an object reference from being published before constructor is finished.

1 Comment

While I would not regard an object as being "immutable" unless it was thread-safe, and unless it guarantees that no visible state will change after a reference has been exposed to the outside world, that does not mean that objects with internal mutable state should not be regarded as "immutable". It's generally okay for an immutable object to change its internal state in ways not visible to the outside world, provided that the only consequence of two threads' effort to change the same aspect of internal state would be the performance of redundant work (as with a string's hashcode).
1

Yes, if you created an object that contained only private members and provided no setters it would be immutable.

Comments

1

A class is immutable if it does not provide any methods that are accessible from the outside that modify the state of the object. So yes, you can create a class that is immutable without making the fields final. Example:

public final class Example {
    private int value;

    public Example(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

However, there is no need to do this in real programs, and it is recommended to always make fields final if your class should be immutable.

Comments

1

I believe the answer is yes.

consider the following object:

public class point{
   private int x; 
   private int y;
   public point(int x, int y)
   {
      this.x =x; 
      this.y =y;
    }

   public int getX()
    {
       return x;
    }

    public int getY()
    { 
        return y;
    }

}

This object is immutable.

Comments

0

Yes. Make the fields private. Don't change them in any methods other than the constructor. Of course, that being the case, why wouldn't you label them as final???

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.