Программирование на Java
Шрифт:
Для организации такого процесса стандартный механизм сериализации строит граф, включающий в себя все участвующие объекты и ссылки между ними. Если очередная ссылка указывает на некоторый объект, сначала проверяется – нет ли такого объекта в графе. Если есть – объект второй раз не сериализуется. Если нет – новый объект добавляется в граф.
При построении графа может встретиться объект, порожденный от класса, не реализующего интерфейс 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;
}
}
}
Пример 15.12.
В этой программе
Выполнение этой программы приведет к выводу на экран примерно следующего:
Constructing line: 1
Constructing line: 2
line 1 = Line@7d39
line 2 = Line@4ec
Read objects:
Line: 1
Object reference: Line@331e
from point (1.0,1.0) reference=Point@36bb
to point (2.0,2.0) reference=Point@386e
Line: 2
Object reference: Line@6706
from point (2.0,2.0) reference=Point@386e
to point (3.0,3.0) reference=Point@68ae
Line: 1
Object reference: Line@331e
from point (1.0,1.0) reference=Point@36bb
to point (2.0,2.0) reference=Point@386e
Пример 15.13.
Из примера видно, что после восстановления у линий сохраняется общая точка, описываемая одним и тем же объектом (хеш-код 386e ).
Третий записанный объект идентичен первому, причем, совпадают даже объектные ссылки. Несмотря на то, что при записи третьего объекта значение index было изменено на 3, в десериализованном объекте оно осталось равным 1. Так произошло потому, что объект, описывающий первую линию, уже был задействован в сериализации и, встретившись во второй раз, повторно записан не был.
Чтобы указать, что сеанс сериализации завершен, и получить возможность передавать измененные объекты, у ObjectOutputStream нужно вызвать метод reset. В рассматриваемом примере для этого достаточно убрать комментарий в строке
//oos.reset;
Если теперь запустить программу, то можно увидеть, что третий объект получит номер 3.
Constructing line: 1
Constructing line: 2
line 1 = Line@ea2dfe
line 2 = Line@7182c1
Read objects:
Line: 1
Object reference: Line@a981ca
from point (1.0,1.0) reference=Point@1503a3
to point (2.0,2.0) reference=Point@a1c887
Line: 2
Object reference: Line@743399
from point (2.0,2.0) reference=Point@a1c887
to point (3.0,3.0) reference=Point@e7b241
Line: 3
Object reference: Line@67d940
from point (1.0,1.0) reference=Point@e83912
to point (2.0,2.0) reference=Point@fae3c6
Пример 15.14.
Однако это будет уже новый объект, ссылка на который отличается от первой считанной линии. Более того, обе точки будут также описываться новыми объектами. То есть в новом сеансе все объекты были записаны, а затем восстановлены заново.