Смекни!
smekni.com

Сериализация объектов (стр. 3 из 3)

Поэтому сериализации можно подвергнуть не каждый объект, а только тот, который реализует интерфейс Serializable. Этот интерфейс не содержит ни полей, ни методов. Реализовать в нем нечего. По сути дела запись

class A implements Serializable{…}

это только пометка, разрешающая сериализацию класса А.

В Java процесс сериализации максимально автоматизирован. Достаточно создать объект класса ObjectOutputStream, связав его с выходным потоком, и выводить в этот поток объекты методом writeObject():

MyClass me = new MyClass («abc», -12, 5.67e‑5);

int[] arr = {10, 20, 30};

ObjectOutputStream oos = new ObjectOutputStream (

new FileOutputStream («myobjects.ser»));

oos.writeObject(me);

oos.writeObject(arr);

oos.writeObject («Some string»);

oos.writeObject (new Date());

oos.flush();

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

Если в объекте присутствуют ссылки на другие объекты, то они тоже сериализуются, а в них могут быть ссылки на другие объекты, которые опять-таки сериализуются, и получается целое множество причудливо связанных между собой сериализуемых объектов. Метод writeObject() распознает две ссылки на один объект и выводит его в выходной поток только один раз. К тому же, он распознает ссылки, замкнутые в кольцо, и избегает зацикливания.

Все классы объектов, входящих в такое сериализуемое множество, а также все их внутренние классы, должны реализовать интерфейс Serializable, в противном случае будет выброшено исключение класса NotSerializableException и процесс сериализации прервется. Многие классы J2SDK реализуют этот интерфейс. Учтите также, что все потомки таких классов наследуют реализацию (может быть сериализацию?). Например, класс java.awt. Component реализует интерфейс Serializable, значит, все графические компоненты можно сериализовать. Не реализуют этот интерфейс обычно классы, тесно связанные с выполнением программ, например, java.awt. Toolkit. Состояние экземпляров таких классов нет смысла сохранять или передавать по сети. Не реализуют интерфейс Serializable и классы, содержащие внутренние сведения Java «для служебного пользования».

Десериализация происходит так же просто, как и сериализация:

ObjectlnputStream ois = new ObjectInputStream (

new FilelnputStream («myobjects.ser»));

MyClass mcl = (MyClass) ois.readObject();

int[] a = (int[]) ois.readObject();

String s = (String) ois.readObject();

Date d = (Date) ois.readObject();

Приложение 6. Клонирование при помощи сериализации

Под клонированием объекта подразумевают получение его точной копии, независимой от оригинала. Таким образом, изменение параметров объекта-клона не влияет на оригинал, верно и обратное: изменение оригинала не влияет на клон.

Сериализация – один из методов для клонирования объектов. Суть его состоит в следующем: записать исходный объект в поток вывода, а затем считать обратно. В результате получается совершенно новый объект, по свойствам идентичный оригиналу.

Необходимо понимать, что данный способ не является оптимальным в силу следующих причин:

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

– клонирование сериализацией работает несколько медленнее обчного метода клонирования.

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

Для реализации метода рекомендуется использовать следующую схему.

– Создаётся класс SerialCloneable, имплементирующий интерфейсы Cloneable и Serializable.

– Класс SerialCloneable имеет единственный метод clone(), в котором происходит сериализация объекта. Метод clone() возвращает объект из входного потока.

– Класс, который должен содержать поддержку клонирования, наследуется от класса SerialCloneable.

Приложение 7. Пример кода классов Employee и Manager

public class Manager extends Employee {

private Employee secretary;

public Manager (String n, double s, int year, int month, int day) {

super (n, s, year, month, day);

secretary = null;

}

public void setSecretary (Employee s) {

secretary = s;

}

}

public class Employee implements Serializable {

private String name;

private double salary;

private Date hireDay;

public Employee(){};

public Employee (String n, double s, int year, int month, int day) {

name = n;

salary = s;

GregorianCalendar calendar = new GregorianCalendar (year, month‑1, day);

hireDay = calendar.getTime();

}

public String getName() {

return name;

}

public double getSalary() {

return salary;

}

public Date getHireDay() {

return hireDay;

}

public void raiseSalary (double byPercent) {

double raise=salary*byPercent/100;

salary+=raise;

}

}