3

In Effective Java, Bloch recommends to make all the fields final in making an object immutable .

Is it necessary to do so ? Won't just not giving accessor methods make it immutable.

For example

class A {
      private int x;
      A (int x) {
          this.x = x;
      }
}

The above class is immutable even if I don't declare x as final right ? Am I missing something ?

NullUserException
  • 83,810
  • 28
  • 209
  • 234
user2434
  • 6,339
  • 18
  • 63
  • 87
  • Accessor methods (e.g. `getX()`) are fine, it's 'mutator' methods (e.g. `setX()`) that are the problem. – Grundlefleck Oct 01 '11 at 09:38
  • @user2434 You can have a class that is immutable even though all the fields are not declared as final . But that would mean that the immutability of the non final field does not effect the immutability of the object. Actually String is an example of such a class . See http://stackoverflow.com/questions/11282219/why-string-class-is-immutable-even-though-it-has-a-non-final-field-called-hash – Inquisitive Jul 03 '12 at 08:12
  • @Grundlefleck: get() can also be problematic, even with finals. If you have an `int[]` for e.g. elements in a set, then `get()` on that int allows users to change it. So one should also be careful with `get()`. – user1111929 Sep 09 '12 at 08:44

7 Answers7

6

In addition to @Bozho's point, declaring a field as final means that it can be safely accessed without any synchronization.

By contrast, if the field is not final there is a small risk that another thread will see an anomalous value for the field if it accesses it without proper synchronization. This can happen even if nothing changes the field's value after object construction!

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
4

It is not "completely" immutable, because you can change the values. Next thing will be someone else on the team assigning a new value to the field. final indicates the intention of immutability.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Outside of reflection, it is 'completely' immutable. The fact that it is more prone to be made immutable by programmer error is valid, but it doesn't change that fact that the answer to his question is actually yes. – Robin Sep 29 '11 at 14:42
3

The class 'Effectively Immutable', as Java Concurrency In Practice defines the term.

This means that, as long as references to instances are 'safely published', they are immutable. Safely publishing the reference involves using synchronisation such that the Java Memory Model (JMM) can guarantee that callers will see the value of the field fully written. For example, if the field is not final, and an instance is constructed and passed to another thread, the other thread may see the field in an undefined state (such as null if it's an object reference, or only half of a 64-bit long field).

If the instance is only used in a single thread, then the distinction doesn't matter. This is because the JMM uses 'within-thread as-if-serial' semantics. Thus the assignment of a field within a constructor will always happen before the field can be read.

If the field was final, the JMM would guarantee that callers would see the correct value, no matter how the reference was published. So final has a benefit if you want to pass the instance to other threads without using forms of synchronisation.

Grundlefleck
  • 124,925
  • 25
  • 94
  • 111
2

You could also do that, but the compiler will help you when you declare it final. As soon as you try to assign a new value to a member variable the compiler will throw an error.

leifg
  • 8,668
  • 13
  • 53
  • 79
  • Assuming that I declare 'x' as final, I can do A a = new A(5) and in the next line write a = new A(7). The compiler does not warn me anything . Am I missing something ? – user2434 Sep 29 '11 at 14:23
  • 1
    @user2434 - Then you have created two immutable instance of A and assigned them both to the same variable. The first will now get GC'ed. This has nothing to do with immutability of A. – Robin Sep 29 '11 at 14:36
2

In it's current form, yes, this class is immutable. Ignoring reflection of course.

However as @Bozho says it only takes someone adding a method to change that.

Making x final provides extra safety and makes your intent clear.

James DW
  • 1,815
  • 16
  • 21
  • +1 At least someone pointed out that what he has is actually immutable. Pointing out that it is more prone to being altered to be immutable, or that it is not as threadsafe are all valid points, but the actual question of whether it is immutable should still be answered. – Robin Sep 29 '11 at 14:39
2

You can always set a private field with setAccessible. This is how Spring, Hibernate and other such frameworks operate. If it is also possible to subclass A, this raises the question about whether all instances of A are immutable or not.

The main benefit from making immutability explicit is that it makes the intention of the coder clear. There can not be a setter for final so someone reading the code does not have to look for it. I usually also state the intention of immutability in the class comment.

(I assume you know the benefits of immutability in general, because you asked just about the mechanisms.)

lokori
  • 436
  • 5
  • 6
0

Apart from the possibility to add code that changes the value of non-final field, the JVM treats final and non-final fields differently. The Java memory model has a section on the subject (quite non-casual reading).

gustafc
  • 28,465
  • 7
  • 73
  • 99