Стандартный механизм сериализации в Java
При беглом знакомстве стандартный механизм сериализации в Java может по
-
казаться наиболее простым и понятным. Но в действительности он имеет мно
-
го минусов – мы кратко рассмотрим их, но это не значит, что данный механизм
не имеет практической ценности.
Основная предпосылка проста: преобразовать экземпляр объекта в байты.
Эти байты можно сохранить на диск или отправить в сеть и при необходи
-
198
Сериализация и транспорты
мости собрать из них исходный объект. Однако для этого необходимо, чтобы
программа, пытающаяся получить объект, сериализованный таким способом,
имела точное определение Java-объекта – виртуальная машина Java (JVM)
должна иметь класс, соответствующий полному имени класса объекта и опре
-
деляющий свойства и методы с именами, совпадающими с именами свойств
и методов в исходном классе.
Рассмотрим простой пример: представьте, что вы унаследовали код прило
-
жения от стороннего подрядчика. Они использовали класс с именем
Chapter
,
имеющий множество свойств и методов, полезных для объекта, представляю
-
щего главу в книге. Однако имя пакета (а значит, и полное имя класса – так на
-
зываемое «каноническое» имя) включало доменное имя подрядчика, и когда
вы стали владельцем исходного кода приложения, у вас не было пакета с соот
-
ветствующим именем. Обычно в этом нет ничего страшного – вы можете соз
-
дать свой класс
Chapter
, имеющий или не имеющий методы и свойства с имена
-
ми, аналогичными именам методов и свойств в старом классе
Chapter
. Однако
подрядчик нарушил общепринятые соглашения, сериализовав экземпляры
Chapter
в байты и записав их в BLOB-поля в локальной базе данных SQLite. Это
означает, что вы
должны
иметь пакет с именем, точно совпадающим с преды
-
дущим каноническим именем, включая домен подрядчика. Когда вы решили
выяснить, как работает экземпляр
Chapter
в вашем собственном приложении,
то обнаружили, что этот промежуточный класс нужен, только чтобы десериа
-
лизовать информацию из базы данных, преобразовать в обновленную версию
класса
Chapter
и сохранить его свойства в обновленной базе данных. Это не
только приводит к путанице, потому что эту историю приходится рассказы
-
вать каждому новому разработчику, но также каждый раз, когда вы открываете
Android Studio, вы видите этот неиспользуемый пакет подрядчика в верхней
части исходного кода, изобилующего определениями классов, которые сущест-
вуют, только чтобы дать пользователям предыдущей версии приложения пере
-
нести свой контент в новое приложение.
А теперь, памятуя о недостатках, посмотрим, как можно использовать стан
-
дартную сериализацию Java на практике.
Первое, что нужно знать, – для использования стандартного механизма
сериализации в Java сериализуемый класс должен реализовать интерфейс
Serializable
. Этот интерфейс не определяет методов, которые нужно реали
-
зовать; ваш класс просто должен объявить, что он поддерживает этот интер
-
фейс.
Также вы должны определить в классе свойство
long
serialVersionUID
для хра
-
нения идентификатора сериализации, например
private
static
final
long
serial
VersionUID
=
12345467890;
. Здесь можно использовать любое допустимое значение
типа
Long
, лишь бы оно было уникальным среди ваших сериализуемых классов.
Большинство сред разработки для Java или Android могут автоматически гене
-
рировать эти свойства, выбирая правильное имя и значение.
После этого остается только записать объект в файл, используя классы
In
putStream
и
OutputStream
, с которыми мы познакомились в главе 6. Давайте по
-
смотрим, как сериализовать простой класс, используя все тот же класс
Author
,
который мы определили выше:
Android
199
Java
// допустим, "myObject" -- допустимый экземпляр
try {
File file = new File(context.getFilesDir(), "data.obj");
FileOutputStream fileOutputStream = new FileOutputStream(file);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(myObject);
objectOutputStream.close();
} catch (IOException e) {
// ошибка
}
Kotlin
// допустим, "myObject" -- допустимый экземпляр
try {
val file = File(context.getFilesDir(), "data.obj")
val fileOutputStream = FileOutputStream(file)
val objectOutputStream = ObjectOutputStream(fileOutputStream)
objectOutputStream.writeObject(myObject)
objectOutputStream.close()
fileOutputStream.close()
} catch (i: IOException) {
// ошибка
}
Теперь у вас есть файл с именем data.obj, который содержит байты, пред
-
ставляющие экземпляр объекта. Обратите внимание, что это полная копия
и ее можно десериализовать обратно в состояние, имевшее место до сериа
-
лизации, при условии что файл класса находится в CLASSPATH в момент десе
-
риализации. Обратное преобразование также выглядит довольно знакомым:
Java
try {
FileInputStream fileInputStream = new FileInputStream("data.obj");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Author author = (Author) objectInputStream.readObject();
objectInputStream.close();
fileInputStream.close();
} catch (IOException | ClassNotFoundException e) {
// ошибка
}
Kotlin
try {
val fileInputStream = FileInputStream("data.obj")
val objectInputStream = ObjectInputStream(fileInputStream)
val author = objectInputStream.readObject() as Author
objectInputStream.close()
fileInputStream.close()
} catch (e: IOException) {
// ошибка
200
Сериализация и транспорты
} catch (e: ClassNotFoundException) {
// ошибка
}
Вот и все! Как уже отмечалось, большинство разработчиков предпочитают
формат JSON при организации сетевых взаимодействий, но, как было показа
-
но выше, в вашем распоряжении имеется много других вариантов. Желающим
мы советуем также познакомиться с protobuffs – новым способом передачи
данных от Google.
iOS
Существует много разных способов преобразования данных в представле
-
ния, пригодные для транспортировки, и обратно. Обычно это делается для
передачи данных в сетевых запросах, и с этой целью наиболее часто исполь
-
зуются форматы JSON и XML, причем в последние годы формат JSON поль
-
зуется большей популярностью, чем XML. Процесс преобразования между
этими двумя форматами и экземплярами объектов в Swift сильно отлича
-
ется. Существует также дополнительный формат, используемый почти ис
-
ключительно компанией Apple, – список свойств. Это особая разновидность
XML, которую приложения для iOS (и macOS) могут использовать для чтения
и записи данных.
Современные версии Swift предлагают намного более удобную и простую
реализацию преобразования данных, чем в прошлом, но все же она имеет не
-
которые сложности. Проще говоря, нам есть что рассказать вам.
Do'stlaringiz bilan baham: |