Материал предоставлен https://it.rfei.ru

Транзитивные и изменчивые поля

Транзитные (transient) поля

При сохранении объектов используется механизм сериализации. Сериализация преобразует объекты в выходной формат, удобный для дальнейшего процесса их сохранения. Позже состояние объектов может быть извлечено, и оно будет таким же, как на момент сериализации. О таких объектах говорят, что они сохраняемы (persistent).

Поле может быть определено как транзитное в описании класса, указывая этим на то, что его значение не должно сохраняться в постоянном хранилище. В следующем примере поле currentTemperature объявлено как transient в строке (1), потому что текущая температура с большой вероятностью изменится в следующие дни, когда объект будет восстановлен из хранилища. Однако значение поля mass, объявленное в строке (2), скорее останется неизменным. Когда объекты класса Experiment сериализуются, значение поля currentTemperature для них не сохраняется, а поле mass будет частью состояния сериализованного объекта.

class Experiment implements Serializable {
    // ...
    // Значение поля currentTemperature не сохраняется
    transient int currentTemperature;     // (1) Транзитное значение.
    double mass;                          // (2) Постоянное значение.
}

Задание модификатора transient для статических переменных избыточно, поэтому его лучше не использовать. Статические переменные не являются частью постоянного состояния сериализованного объекта.

Изменчивые (volatile) поля

Во время выполнения откомпилированный код может кешировать значения полей с целью повышения производительности. Поскольку потоки разделяют одно и то же поле, жизненно важно не допустить кеширования, чтобы не разрушить целостность данных — например, во время операций изменения значения в поле. Модификатор volatile (изменчивый) может использоваться, чтобы сообщить компилятору о том, что ему не следует пытаться выполнять оптимизацию доступа к полю, что может привести к непредсказуемым результатам, когда к полю обратятся несколько потоков.

В простом случае, который показан ниже, значение поля clockReading может быть непредсказуемым образом изменено другим потоком, пока основной поток выполняет задачу, которая включает использование текущего значения поля clockReading. Объявление поля в качестве volatile гарантирует, что действие по изменению будет выполняться с главной переменной поля, а операция чтения всегда будет возвращать правильное текущее значение.

class VitalControl {
    // ...
    volatile long clockReading;
    // Два последующих чтения могут привести к разным результатам
}

Таблица 4.5. Сводная таблица дополнительных модификаторов членов

Модификаторы Поля Методы
static Определяет переменную класса Методы класса
final Определяет константу Не будут переопределены
abstract Не применимо Тело метода не определено
synchronized Не применимо Один поток выполняет один метод
native Не применимо Метод реализован на другом языке
transient Значение поля не включается при сериализацииНе применимо
volatile Компилятор не оптимизирует доступ к значениюНе применимо
Другие модификаторы для членовОбъявления и управление доступом