问题
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 ?
回答1:
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!
回答2:
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.
回答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.
回答4:
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:
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.
回答6:
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.)
回答7:
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).
来源:https://stackoverflow.com/questions/7598245/immutable-in-java