Философия Java3
вернуться

Эккель Брюс

Шрифт:

"\п дата " + date + "\п пароль " + password;

public static void main(String[] args) throws Exception { Logon a = new Logon("Пользователь". "Пароль"), print("Сеанс a = " + a). ObjectOutputStream о = new ObjectOutputStream(

new FileOutputStream("Logon out")), о writeObject(a); о closeO,

TimeUnit.SECONDS.sleep(l). // Задержка // Восстановление-

ObjectlnputStream in = new ObjectInputStream(

new FileInputStream("Logon out")), print ("Восстановление объекта Время: " + new DateO); a = (Logon)in readObjectO, print("Сеанс a = " + a).

}

} /* Output

Сеанс a = информация о сеансе пользователь- Пользователь дата- Sat Nov 19 15-03 26 MST 2005 пароль Пароль

Восстановление объекта. Время: Sat Nov 19 15.03 28 MST 2005

Сеанс а = информация о сеансе пользователь. Пользователь дата Sat Nov 19 15.03 26 MST 2005 пароль, null

*/// ~

Поля date и username не имеют модификатора transient, поэтому сериализация для них проводится автоматически. Однако поле password описано как transient и поэтому не сохраняется на диске; механизм сериализации его также игнорирует. При восстановлении объекта поле password равно null. Заметьте, что при соединении строки (String) со ссылкой null перегруженным оператором + ссылка null автоматически преобразуется в строку null.

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

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

Альтернатива для Externalizable

Если вас по каким-либо причинам не прельщает реализация интерфейса Externalizable, существует и другой подход. Вы можете реализовать интерфейс Serializable и добавить (заметьте, что я сказал «добавить», а не «переопределить» или «реализовать») методы с именами writeObject и readObject. Они автоматически вызываются при сериализации и восстановлении объектов. Иначе говоря, эти два метода заменят собой сериализацию по умолчанию.

Эти методы должны иметь жестко фиксированную сигнатуру:

private void writeObject(ObjectOutputStream stream)

throws IOException;

private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException

С точки зрения проектирования программы этот подход вообще непонятен. Во-первых, можно подумать, что, раз уж эти методы не являются частью базового класса и не определены в интерфейсе Serializable, у них должен быть свой собственный интерфейс. Но так как методы объявлены закрытыми (private), вызываться они могут лишь членами их собственного класса. Однако члены обычных классов их не вызывают, вместо этого вызов исходит из методов writeObject и readObject классов ObjectlnputStream и ObjectOutputStream. (Я не стану разражаться долгой тирадой о выборе тех же имен методов, а скажу лишь одно слово: неразумно.) Интересно, каким образом классы ObjectlnputStream и ObjectOutputStream обращаются к закрытым членам другого класса? Можно лишь предположить, что это относится к таинству сериализации.

Так или иначе, все методы, описанные в интерфейсе, реализуются как открытые (public), поэтому, если методы writeObject и readObject должны быть закрытыми (private), они не могут быть частью какого-либо интерфейса. Однако вам необходимо строго следовать указанной нотации, и результат очень похож на реализацию интерфейса.

Судя по всему, при вызове метода ObjectOutputStream.writeObject передаваемый ему объект Serializable тщательно анализируется (вне всяких сомнений, с использованием механизма рефлексии) в поисках его собственного метода writeObject. Если такой метод существует, процесс стандартной сериализации пропускается, и вызывается метод объекта writeObject. Аналогичные действия происходят и при восстановлении объекта.

Существует и еще одна хитрость. В вашем собственном методе writeObject можно вызвать используемый в обычной сериализации метод writeObject, для этого вызывается метод defaultWriteObject. Аналогично, в методе readObject можно вызвать метод стандартного восстановления defaultReadObject. Следующий пример показывает, как производится пользовательское управление хранением и восстановлением объектов Serializable:

//: io/SerialCtl java

// Управление сериализацией с определением собственных // методов writeObjectO и readObjectO. import java.io.*;

public class SerialCtl implements Serializable { private String a; private transient String b: public SerialCtl(String aa, String bb) {

a = "He объявлено transient: " + aa: b = "Объявлено transient: " + bb:

}

public String toStringO { return a + "\n" + b: } private void writeObject(ObjectOutputStream stream) throws IOException {

stream.defaultWriteObject: stream.writeObject(b);

}

private void readObject(ObjectInputStream stream)

throws IOException. ClassNotFoundException { stream.defaultReadObject, b = (String)stream.readObjectO.

}

public static void main(String[] args) throws IOException, ClassNotFoundException {

SerialCtl sc = new SerialCtl("Testl". "Test2"); System out.printin("Перед записью \n" + sc); ByteArrayOutputStream buf= new ByteArrayOutputStream; ObjectOutputStream о = new ObjectOutputStream(buf); о writeObject(sc). // Now get it back.

ObjectlnputStream in = new ObjectInputStream(

new ByteArraylnputStream(buf.toByteArrayO)); SerialCtl sc2 = (SerialCtl)in readObject; System out println("После восстановления:\n" + sc2),

  • Читать дальше
  • 1
  • ...
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • ...

Private-Bookers - русскоязычная библиотека для чтения онлайн. Здесь удобно открывать книги с телефона и ПК, возвращаться к сохраненной странице и держать любимые произведения под рукой. Материалы добавляются пользователями; если считаете, что ваши права нарушены, воспользуйтесь формой обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • help@private-bookers.win