Модификаторы transient и volatile
Java определяет два интересных модификатора типов: transient и volatile. Эти модификаторы служат для управления некоторыми специфическими ситуациями.
Когда экземпляр переменной объявлен как transient, его значение не должно удерживаться, когда объект сохраняется. Например:
class Т transient int а; //не будет удерживаться
int b; // будет удерживаться
>
Здесь если объект типа Т записывается в область постоянного хранения, то содержимое а не должно сохраняться, а содержимое b — должно.
Модификатор volatile сообщает компилятору, что переменная, модифицированная с помощью volatile, может быть неожиданно изменена другими частями вашей программы. Одна из таких ситуаций возникает в мнОтопоточных программах. (Вы видели пример в главе 11.) В многопоточных программах иногда два или более потоков управления разделяют доступ к одной и той же переменной. Из соображений эффективности каждый поток может хранить свою собственную приватную копию этой переменной. Реальная (или мастер-) копия переменной обновляется в различные моменты, например при входе в метод synchronized. Хотя такой подход работает нормально, все же иногда он недостаточно эффективен. В некоторых случаях все, что действительно происходит — это то, что мастер-копия переменной всегда отражает ее текущее состояние. Чтобы обеспечить это, просто объявите переменную как volatile, что сообщит компилятору, что он должен всегда использовать мастер-копию переменной volatile (или же, как минимум, всегда держать приватные ее копии синхронизированными с мастер-копией и наоборот). Кроме того, доступ к мастер-копии переменной должен осуществляться в том же порядке, как он выполнялся к приватной копии.
Для чего нужен модификатор transient?
Сериализация — это преобразование экземпляра класса в форму, пригодную для его сохранения (например в файл, в БД или для передачи по сети). Сериализованные объекты можно затем восстановить (десериализовать).
Свойства класса, помеченные модификатором transient , не сериализуются.
Обычно в таких полях хранится промежуточное состояние объекта, которое, к примеру, проще вычислить, чем сериализовать, а затем десериализовать. Другой пример такого поля — ссылка на экземпляр объекта, который не требует сериализации или не может быть сериализован.
Сериализация объектов. Ключевое слово transient . Примеры
Язык программирования Java имеет мощные средства для обеспечения механизма сериализации. Сериализация – возможность объекта сохранять собственные данные (состояние объекта) в байтовом потоке с целью дальнейшего восстановления этих данных (состояния) при следующих запусках программы. Другими словами, текущие значения внутренних переменных в объекте можно сохранить (например, в файл), а затем восстановить в нужный момент.
Механизм сериализации дает следующие преимущества:
- объект, для которого применяется сериализация, существует между запусками программы. Этот механизм называется легковесным долгосрочным сохранением объектов (lightweight persistence). Объект сначала сохраняется на диске, затем восстанавливается в начальное состояние при следующем запуске программы;
- обеспечивается удаленный вызов методов Java, что позволяет работать с объектами, которые «размещаются» на удаленных компьютерах так, если бы они существовали на вашем компьютере;
- необходимость сохранения текущей информации о состоянии визуальных компонент JavaBean;
- использование в объектах классов, которые требуют сохранения текущего состояния.
2. Реализация сериализации в программах на Java
В языке Java для того, чтобы осуществить сериализацию объекта в программе нужно придерживаться следующих рекомендаций. Все классы, которые связаны с сериализацией, должны реализовать интерфейс Serializable . Это значит, что класс, реализующий сериализацию, должен выглядеть приблизительно следующим образом:
class MySerializeClass implements Serializable
так же класс, экземпляр которого сериализуется также должен реализовать интерфейс Serializable :
class MyDataClass implements Serializable
2.1. Запись объекта в файл
Если создан объект dataObj некоторого класса DataClass , то чтобы сохранить этот объект нужно выполнить следующие действия.
1. Создать исходный поток fOut типа OutputStream . В случае сохранения объекта в файле создается исходный поток типа FileOutputStream
FileOutputStream fOut = new FileOutputStream(filename);
здесь filename – имя файла, в котором будет сохранен объект.
Класс FileOutputStream есть подклассом абстрактного класса OutputStream .
2. Упаковать файловый объект fOut в другой объект типа ObjectOutputStream
ObjectOutputStream objOut = new ObjectOutputStream(fOut);
В результате создается поток objOut .
3. Записать экземпляр dataObj в поток objOut . Для этого используется встроенный метод writeObject()
objOut.writeObject(dataObj);
4. Закрыть оба созданных потока
objOut.close(); fOut.close();
2.2. Чтение объекта из файла
Если объект предварительно сохранен, то для того, чтобы восстановить его состояние из файла, нужно выполнить следующие действия.
1. Создать экземпляр fInput класса FileInputStream
FileInputStream fInput = new FileInputStream(filename);
здесь filename – имя файла (тип String ), в котором предварительно был сохранен объект.
2. Создать экземпляр objInput класса ObjectInputStream , в который упаковать экземпляр fInput класса FileInputStream
ObjectInputStream objInput = new ObjectInputStream(fInput);
3. Прочитать экземпляр с помощью метода readObject() . Например, если нужно прочитать экземпляр класса DataClass , то код чтения будет следующим
DataClass dObj = (DataClass)objInput.readObject();
4. Закрыть потоки fInput и objInput
objInput.close(); fInput.close();
3. Какое назначение модификатора transient ?
Модификатор transient используется, если возникает необходимость сохранить объект (экземпляр) класса (выполнить сериализацию). Модификатор transient устанавливается перед объявлением внутренней переменной класса, значение которой не должно сохраняться в случае сохранения объекта. С помощью модификатора transient можно программно указать данные, которые не нужно сохранять при сериализации объекта.
Например. В нижеследующем классе Book переменная price объявлена с модификатором transient . Это значит, что при записи в файл любого экземпляра класса Book , записываться будут значения переменных title , author , year кроме переменной price .
class Book < String title; String author; int year; transient double price; // Эта переменная сохраняться не будет >
4. Пример сериализации и использования модификатора transient . Классы ObjectInputStream и ObjectOutputStream
В примере объявляется два класса:
- класс DataClass , содержащий данные, которые будут сохранены. Сохраняется экземпляр этого класса;
- класс SerializeClass , который содержит методы записи экземпляра типа DataClass .
Оба класса реализуют интерфейс Serializable .
В классе DataClass объявляются:
- внутренние переменные a , b . Переменная b объявлена как transient -переменная. Это означает, что при записи в файл экземпляра типа DataClass , значение переменной b записываться не будет;
- конструктор DataClass(int, int) ;
- методы доступа к внутренним переменным GetA() , GetB() , SetA() , SetB() ;
- метод Print() , выводящий значение внутренних переменных.
В классе SerializeClass объявляются:
- метод SaveData() , реализующий запись экземпляра типа DataClass в файл;
- метод ReadData() , возвращающий экземпляр типа DataClass , который был ранее записан в файл.
// Сериализация объектов import java.io.*; // Класс, экземпляр которого нужно будет записать/считать из файла class DataClass implements Serializable < // Внутренняя переменная private int a; private transient int b; // эта переменная сохраняться не будет // Конструктор DataClass(int a, int b) < this.a = a; this.b = b; > // Методы доступа int GetA() < return a; > int GetB() < return b; > void SetA(int a) < this.a = a; > void SetB(int b) < this.b = b; > // Метод, выводящий данные void Print() < System.out.println("a color: #0000ff;">", b color: #008000;">// Класс, который содержит методы сериализации (записи/чтения данных) класса DataClass public class SerializeClass implements Serializable < // Метод, осуществляющий запись экземпляра класса DataClass в файл filename static void SaveData(DataClass dataObj, String filename) throws ClassNotFoundException, IOException < // 1. Создать экземпляр класса FileOutputStream - создать файловый поток FileOutputStream fOut = new FileOutputStream(filename); // 2. Создать экземпляр objOut класса ObjectOutputStream - поток записи объектов ObjectOutputStream objOut = new ObjectOutputStream(fOut); // 3. Записать экземпляр dataObj в поток objOut // 3.1. Записать комментарий objOut.writeObject("Storage the dataObj instance\n"); // 3.2. Записать экземпляр objOut.writeObject(dataObj); // 4. Закрыть поток objOut objOut.close(); // Закрыть файловый поток fOut.close(); > static DataClass ReadData(String filename) throws ClassNotFoundException, IOException < // 1. Создать экземпляр класса FileInputStream FileInputStream fInput = new FileInputStream(filename); // 2. Создать экземпляр класса ObjectInputStream ObjectInputStream objInput = new ObjectInputStream(fInput); // 3. Прочитать данные из файла filename в экземпляр dataObj // 3.1. Прочитать строку комментария String s = (String)objInput.readObject(); // 3.2. Прочитать экземпляр типа DataClass DataClass dObj = (DataClass)objInput.readObject(); // 4. Закрыть потоки objInput.close(); fInput.close(); // 5. Вернуть результат return dObj; > public static void main(String[] args) throws ClassNotFoundException, IOException < // 1. Записать экземпляр класса DataClass в файл "myFile.dat" // 1.1. Создать объект класса DataClass DataClass objData = new DataClass(5, 8); // 1.2. Записать объект objData в файл "myFile.dat" SaveData(objData, "myFile.dat"); // 2. Прочитать экземпляр класса DataClass из файла "myFile.dat" // 2.1. Объявить ссылку на DataClass DataClass objData2; // 2.2. Прочитать данные в objData2 objData2 = ReadData("myFile.dat"); // 2.3. Вывести данные objData2.Print(); // a = 5, b = 0 - значение переменной b не записывалось > >
5. Сохраняются ли методы класса во время сериализации?
Нет. При использовании механизма сериализации, сохраняются только данные (внутренние переменные).
6. Пример класса, который содержит методы сериализации экземпляра данного класса
В примере разработан класс Sphere , в котором определенны методы:
- записи в файл текущего экземпляра класса;
- чтение данных из файла текущего класса.
Класс содержит методы сериализации экземпляра данного класса.
Transient java что это
Исключение, выданное, когда ШАР, предпринятый, чтобы достигнуть объекта и отказавший. Это не индикация, что объект не существует. Вместо этого это просто означает, что никакое дальнейшее определение состояния объекта не было возможно, потому что это не могло быть достигнуто. Это исключение повышается, если попытка установить соединение перестала работать, например, потому что сервер или репозитарий реализации снижаются. Это содержит незначительный код, который дает более подробную информацию о том, что вызвало исключение, и состояние завершения. Это может также содержать строку, описывающую исключение.
Полевая Сводка
Поля org.omg унаследованный от класса. CORBA.SystemException
Сводка конструктора
Конструкции a TRANSIENT исключение с незначительным кодом по умолчанию 0, состоянием завершения CompletionStatus. COMPLETED_NO, и нулевое описание.
Конструкции a TRANSIENT исключение с указанным незначительным кодом и состоянием завершения.
Конструкции a TRANSIENT исключение с указанным сообщением описания, незначительным кодом 0, и состоянием завершения COMPLETED_NO.
Конструкции a TRANSIENT исключение с указанным сообщением описания, незначительным кодом, и состоянием завершения.
Сводка метода
Методы org.omg унаследованный от класса. CORBA.SystemException
Методы java.lang унаследованный от класса. Throwable
Методы java.lang унаследованный от класса. Объект
Деталь конструктора
ПЕРЕХОДНЫЙ ПРОЦЕСС
public TRANSIENT()
Конструкции a TRANSIENT исключение с незначительным кодом по умолчанию 0, состоянием завершения CompletionStatus. COMPLETED_NO, и нулевое описание.
ПЕРЕХОДНЫЙ ПРОЦЕСС
Конструкции a TRANSIENT исключение с указанным сообщением описания, незначительным кодом 0, и состоянием завершения COMPLETED_NO.
ПЕРЕХОДНЫЙ ПРОЦЕСС
public TRANSIENT(int minor, CompletionStatus completed)
Конструкции a TRANSIENT исключение с указанным незначительным кодом и состоянием завершения.
ПЕРЕХОДНЫЙ ПРОЦЕСС
public TRANSIENT(String s, int minor, CompletionStatus completed)
Конструкции a TRANSIENT исключение с указанным сообщением описания, незначительным кодом, и состоянием завершения.
Платформа Java™
Стандарт Эд. 7
Представьте ошибку или функцию
Для дальнейшей ссылки API и документации разработчика, см. Java Документация SE . Та документация содержит более подробные, предназначенные разработчиком описания, с концептуальными краткими обзорами, определениями сроков, обходных решений, и рабочих примеров кода.
Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.
