// Управление сериализацией с определением собственных // методов 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),
}
} /* Output: Перед записью
He объявлено transient- Testl Объявлено transient: Test2 После восстановления-He объявлено transient: Testl Объявлено transient: Test2 *///.-
В данном примере одно из строковых полей класса объявлено с ключевым словом transient, чтобы продемонстрировать, что такие поля при вызове метода defaultWriteObject() не сохраняются. Строка сохраняется и восстанавливается программой явно. Поля класса инициализируются в конструкторе, а не в точке определения; это демонстрирует, что они не инициализируются каким-либо автоматическим механизмом в процессе восстановления.
Если вы собираетесь использовать встроенный механизм сериализации для записи обычных (He-transient) составляющих объекта, нужно при записи объекта в первую очередь вызвать метод defaultWriteObject(), а при восстановлении объекта — метод defaultReadObject(). Это вообще загадочные методы. Например, если вызвать метод defaultWriteObject() для потока ObjectOutputStream без передачи аргументов, он все же как-то узнает, какой объект надо записать, где находится ссылка на него и как записать все его He-transient составляющие. Мистика.
Сохранение и восстановление transient-объектов выполняется относительно просто. В методе main() создается объект SerialCtl, который затем сериализуется потоком ObjectOutputStream. (При этом для вывода используется буфер, а не файл — для потока ObjectOutputStream это несущественно.) Непосредственно сериализация выполняется в строке
о writeObject(sc);
Метод writeObject() должен определить, имеется ли в объекте sc свой собственный метод writeObject(). (При этом проверка на наличие интерфейса или класса не проводится — их нет — поиск метода проводится с помощью рефлексии.) Если поиск успешен, найденный метод вовлекается в процедуру сериализации. Примерно такой же подход наблюдается и при восстановлении объекта методом readObject(). Возможно, это единственное решение задачи, но все равно выглядит очень странно.
Долговременное хранение
Было бы замечательно привлечь технологию сериализации, чтобы сохранить состояние вашей программы для его последующего восстановления. Но перед тем как это делать, необходимо ответить на несколько вопросов. Что произойдет при сохранении двух объектов, содержащих ссылку на некоторый общий третий объект? Когда вы восстановите эти объекты, сколько экземпляров третьего объекта появится в программе? А если вы сохраните объекты в отдельных файлах, а затем десериализуете их в разных частях программы? Следующий пример демонстрирует возможные проблемы:
// io/MyWorld java import java io *. import java util *.
import static net mindview util Print *.
class House implements Serializable {}
class Animal implements Serializable { private String name, private House preferredHouse; Animal(String nm, House h) { name = nm, preferredHouse = h;
}
public String toStringO {
return name + "[" + super.toString() + "], " + preferredHouse + "\n",
public class MyWorld {
public static void main(String[] args) throws IOException, ClassNotFoundException { House house = new HouseO: List
new ByteArrayOutputStream(). ObjectOutputStream ol = new ObjectOutputStream(bufl). ol.writeObject(animals):
01 writeObject(animals). // Записываем второй набор // Запись в другой поток ByteArrayOutputStream buf2 =
new ByteArrayOutputStream(); ObjectOutputStream o2 = new 0bject0utputStream(buf2):
02 writeObject(animals).