Программирование на Java



         

Граф сериализации


До этого мы рассматривали объекты, которые имеют поля лишь примитивных типов. Если же сериализуемый объект ссылается на другие объекты, их также необходимо сохранить (записать в поток байт), а при десериализации – восстановить. Эти объекты, в свою очередь, также могут ссылаться на следующие объекты. При этом важно, что если несколько ссылок указывают на один и тот же объект, то этот объект должен быть сериализован лишь однажды, а при восстановлении все ссылки должны вновь указывать на него одного. Например, сериализуемый объект A ссылается на объекты B и C, каждый из которых, в свою очередь, ссылается на один и тот же объект D. После деeсериализации не должно возникать ситуации, когда B ссылается на D1, а C – на D2, где D1 и D2 – равные, но все же различные объекты.

Для организации такого процесса стандартный механизм сериализации строит граф, включающий в себя все участвующие объекты и ссылки между ними. Если очередная ссылка указывает на некоторый объект, сначала проверяется – нет ли такого объекта в графе. Если есть – объект второй раз не сериализуется. Если нет – новый объект добавляется в граф.

При построении графа может встретиться объект, порожденный от класса, не реализующего интерфейс Serializable. В этом случае сериализация прерывается, генерируется исключение java.io.NotSerializableException.

Рассмотрим пример:

import java.io.*; class Point implements Serializable { double x; double y; public Point(double x, double y) { this.x = x; this.y = y; } public String toString() { return "("+x+","+y+") reference="+super.toString(); } } class Line implements Serializable { Point point1; Point point2; int index; public Line() { System.out.println("Constructing empty line"); } Line(Point p1, Point p2, int index) { System.out.println("Constructing line: " + index); this.point1 = p1; this.point2 = p2; this.index = index; } public int getIndex() { return index; } public void setIndex(int newIndex) { index = newIndex; } public void printInfo() { System.out.println("Line: " + index); System.out.println(" Object reference: " + super.toString()); System.out.println(" from point "+point1); System.out.println(" to point "+point2); } } public class Main { public static void main(java.lang.String[] args) { Point p1 = new Point(1.0,1.0); Point p2 = new Point(2.0,2.0); Point p3 = new Point(3.0,3.0); Line line1 = new Line(p1,p2,1); Line line2 = new Line(p2,p3,2); System.out.println("line 1 = " + line1); System.out.println("line 2 = " + line2); String fileName = "d:\\file"; try{ // записываем объекты в файл FileOutputStream os = new FileOutputStream(fileName); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(line1); oos.writeObject(line2); // меняем состояние line1 и записываем его еще раз line1.setIndex(3); //oos.reset(); oos.writeObject(line1); // закрываем потоки // достаточно закрыть только поток-надстройку oos.close(); // считываем объекты System.out.println("Read objects:"); FileInputStream is = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(is); for (int i=0; i<3; i++) { // Считываем 3 объекта Line line = (Line)ois.readObject(); line.printInfo(); } ois.close(); } catch(ClassNotFoundException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } }




Содержание  Назад  Вперед