Immutable in java

2019-07-05 13:58发布

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 ?

7条回答
再贱就再见
2楼-- · 2019-07-05 14:18

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.

查看更多
男人必须洒脱
3楼-- · 2019-07-05 14:18

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.)

查看更多
4楼-- · 2019-07-05 14:19

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.

查看更多
甜甜的少女心
5楼-- · 2019-07-05 14:22

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.

查看更多
做个烂人
6楼-- · 2019-07-05 14:27

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.

查看更多
趁早两清
7楼-- · 2019-07-05 14:30

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).

查看更多
登录 后发表回答