9

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

If possible a couple of examples would be helpful.

Rob Hruska
  • 118,520
  • 32
  • 167
  • 192
Vinoth Kumar C M
  • 10,378
  • 28
  • 89
  • 130
  • 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... ;) – Peter Lawrey Sep 21 '11 at 14:13
  • 1
    Why wouldn't you want to use `final` fields? – David Snabel-Caunt Sep 22 '11 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. – Grundlefleck Nov 02 '11 at 22:44
  • possible duplicate of [Must all properties of an immutable object be final?](http://stackoverflow.com/questions/16061030/must-all-properties-of-an-immutable-object-be-final) – Raedwald Jul 04 '14 at 07:36
  • It makes it immutable but not thread safe!!! http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5-110 – Murat Mustafin Jan 13 '17 at 08:10

7 Answers7

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.

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
  • 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 Sep 21 '11 at 14:06
  • @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 Sep 21 '11 at 14:08
  • @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 – lowLatency Oct 07 '13 at 04:05
  • @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. – Heisenbug Oct 07 '13 at 08:42
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.)
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • And what about reflection mechanism ? – Damian Leszczyński - Vash Sep 21 '11 at 13:56
  • 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. ;-). – Damian Leszczyński - Vash Sep 21 '11 at 14:05
  • @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 Sep 21 '11 at 14:09
  • 1
    @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. – Jon Skeet Sep 21 '11 at 14:11
  • @JonSkeet: thanks for explanation: can I edit my answer adding your comment to final class declaration? I think could be useful highlight it. – Heisenbug Sep 21 '11 at 14:16
  • @JonSkeet: with sufficient privileges, final fields can be changed via reflection, but the documentation says it can have unpredictable effects, especially with regard to threading. – ILMTitan Sep 21 '11 at 14:50
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.

irreputable
  • 44,725
  • 9
  • 65
  • 93
  • 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). – supercat Sep 19 '12 at 20:07
1

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

Rig
  • 1,276
  • 3
  • 22
  • 43
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.

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
Karthik Ramachandran
  • 11,925
  • 10
  • 45
  • 53
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.

Jesper
  • 202,709
  • 46
  • 318
  • 350
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???

John B
  • 32,493
  • 6
  • 77
  • 98