Философия Java

Ключевое слово transient


Когда вы управляете сериализацией, возможно появление определенных подобъектов, для который вы не захотите применять механизм сериализации Java для автоматического сохранения и восстановления. В основном это происходит в том случае, если такой подобъект представляет важную информацию, которую вы не хотите сериализовать, например, пароль. Даже если такая информация имеет модификатор private в объекте, так как она сериализуется, то кто-либо может получить доступ для чтения файла или перехватить сетевую передачу.

Один способ предохранения важной части вашего объекта от сериализации, заключающий в реализации Externalizable, показан в предыдущем разделе. Но при этом ничего автоматически не сериализуется и вы должны явно сеарилизовать только нужные вам части внутри writeExternal( ).

Однако если вы работаете с Serializable объектом, вся сериализация происходит автоматически. Для управления этим, вы можете выключить сериализацию полей индивидуально, используя ключевое слово transient, которое говорит: “Не беспокойтесь о сохранении и восстановлении этого — я позабочусь об этом”.

В качестве примера рассмотрим объект Login, хранящий информацию об определенной сессии подключения. Предположим, что как только вы проверили имя пользователя, вы хотите сохранить данные, но без пароля. Простейшим способом является реализация Serializable и пометка поля password ключевым словом transient. Вот как это выглядит:

//: c11:Logon.java

// Демонстрация ключевого слова "transient".

import java.io.*; import java.util.*;

class Logon implements Serializable { private Date date = new Date(); private String username; private transient String password; Logon(String name, String pwd) { username = name; password = pwd; } public String toString() { String pwd = (password == null) ? "(n/a)" : password; return "logon info: \n " + "username: " + username + "\n date: " + date + "\n password: " + pwd; } public static void main(String[] args) throws IOException, ClassNotFoundException { Logon a = new Logon("Hulk", "myLittlePony"); System.out.println( "logon a = " + a); ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream("Logon.out")); o.writeObject(a); o.close(); // Задержка:


int seconds = 5; long t = System.currentTimeMillis() + seconds * 1000; while(System.currentTimeMillis() < t) ; // Теперь получаем его обратно:

ObjectInputStream in = new ObjectInputStream( new FileInputStream("Logon.out")); System.out.println( "Recovering object at " + new Date()); a = (Logon)in.readObject(); System.out.println( "logon a = " + a); } } ///:~

Вы можете видеть, что поля date и username являются обычными (не transient), и поэтому сериализуются автоматически. Однако поле password является transient, и поэтому не сохраняется на диске; так же механизм сериализации не делает попытку восстановить его. На выходе получаем:

logon a = logon info: username: Hulk date: Sun Mar 23 18:25:53 PST 1997 password: myLittlePony Recovering object at Sun Mar 23 18:25:59 PST 1997 logon a = logon info: username: Hulk date: Sun Mar 23 18:25:53 PST 1997 password: (n/a)

Когда объект восстанавливается, поле password заполняется значением null. Обратите внимание, что toString( ) должна проверять значение на равенство null поля password, потому что если вы попробуете собрать объект String, используя перегруженный оператор ‘+’, а этот оператор обнаружит ссылку, равную null, вы получите NullPointerException. (Новые версии Java могут содержать код для предотвращения этой проблемы.)

Вы также можете заметить, что поле date сохраняется и восстановления с диска и не генерируется заново.

Так как объекты с интерфейсом Externalizable не сохраняют никакие из своих полей автоматически, поэтому ключевое слово transient используется только для объектов с интерфейсом Serializable.


Содержание раздела