Ответ 1
Безопасность инициализации обеспечивает просмотр объекта внешним потоком в полностью сконструированном (инициализированном) состоянии. Предпосылкой является то, что объект не должен публиковаться преждевременно, т.е. в его конструкторе. Как только это будет обеспечено, JMM требует определенного поведения для полей, объявленных как final
. Во-первых, все поля объекта final
гарантируются внешним видимым внешним потоком в его полностью инициализированном состоянии - это не так тривиально, как кажется -
Рассмотрим класс
class A{
List list ;
A() {
list = Arrays.asList(some init expressions that adds 10 elements to list);
}
}
Поток, который обращается к экземпляру list
экземпляра A
, по умолчанию не гарантированно видит 10 элементов в этом списке. Фактически, этот поток даже может видеть list
как null
. Однако, если list
объявлен final
, тогда, как требуется JMM, list
всегда должен быть инициализирован с 10 элементами, которые он имеет.
Во-вторых, эта гарантия инициализации не ограничивается самим полем final
, но рекурсивно распространяется на все связанные с ней объекты. Например, если list
в приведенном выше примере представляет собой список list
, то внешний поток гарантированно будет видеть внутренние списки как полностью инициализированные.
Обратите внимание, что мы не используем synchronized
для достижения этой безопасности в видимости памяти (происходит до отношения).