Каждый из вас знает об этой функции JMM, которая иногда ссылается на объект, может получать значение до завершения конструктора этого объекта.
В JLS7, p. 17.5 окончательную полевую семантику мы также можем прочитать:
Модель использования для полей
final
проста: установите поляfinal
для объекта в этом объектном конструкторе; и не пишите ссылка на объект, который строится в месте, где поток может видеть его до завершения конструктора объекта. Если это, тогда, когда объект рассматривается другим потоком, это нить всегда будет видеть правильно построенную версию этого objectfinal
.(1)
И только после этого в JLS следует пример, демонстрирующий, как не может быть инициализировано поле non-final (1 пример 17.5-1.1) (2)
:
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
Кроме того, в этом вопросе-ответе г-н Грей написал:
Если вы помечаете это поле как
final
, то конструктору гарантируется завершите инициализацию как часть конструктора. В противном случае вы перед его использованием необходимо синхронизировать блокировку.(3)
Итак, вопрос:
1) В соответствии с утверждением (1) нам следует избегать ссылки на неизменяемый объект до завершения его конструктора
2) Согласно приведенному JLS примеру (2) и выводу (3), мы можем смело обмениваться ссылкой на неизменный объект до, его конструктор закончен, т.е. когда все его поля final
.
Нет ли противоречия?
EDIT-1. То, что я точно имею в виду. Если мы будем модифицировать класс таким образом, это поле y
будет также final
(2):
class FinalFieldExample {
final int x;
final int y;
...
следовательно, в reader()
будет гарантировано, что:
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // guaranteed to see 4, isn't it???
Если да, почему мы должны избегать ссылки на объект f
до того, как он завершит конструкцию (согласно (1)), когда все поля f
являются окончательными?