What is import java io serializable

Java IO: Serializable

The Java Serializable interface ( java.io.Serializable is a marker interface your classes must implement if they are to be serialized and deserialized. Java object serialization (writing) is done with the ObjectOutputStream and deserialization (reading) is done with the ObjectInputStream.

That Serializable is a marker interface means that it contains no methods. Therefore, a class implementing Serializable does not have to implement any specific methods. Implementing Serializable thus just tells the Java serialization classes that this class is intended for object serialization.

Serializable Example

Here is an example of a class that implements the Java Serializable interface:

import java.io.Serializable; public static class Person implements Serializable

As you can see, the Person class implements the Serializable interface, but does not actually implement any methods. As mentioned earlier, the Java Serializable interface is just a marker interface so there are no methods to implement.

To see a full example of serializing and deserializing an object that implements Serializable , see my ObjectInputStream tutorial.

serialVersionUID

In addition to implementing the Serializable interface, a class intended for serialization should also contain a private static final long variable named serialVersionUID .

Here is the Person class from before, with a serialVersionUID variable added:

import java.io.Serializable; public static class Person implements Serializable

The serialVersionUID variable is used by Java’s object serialization API to determine if a deserialized object was serialized (written) with the same version of the class, as it is now attempting to deserialize it into.

Imagine that a Person object is serialized to disk. Then a change is made to the Person class. Then you try to deserialize the stored Person object. Now the serialized Person object may not correspond to the new version of the Person class.

To detect such problems a class implementing Serializable should contain a serialVersionUID field. If you make big changes to the class, you should also change its serialVersionUID value.

The Java SDK and many Java IDEs contains tools to generate the serialVersionUID so you don’t have to.

Object Serialization Today

In today’s world (2015 and forward) many Java projects serialize Java objects using different mechanisms than the Java serialization mechanism. For instance, Java objects are serialized into JSON, BSON or other more optimized binary formats. This has the advantage of the objects also being readable by non-Java applications. For instance, JavaScript running in a web browser can natively serialize and deserialize objects to and from JSON.

These other object serialization mechanisms typically do not require your Java classes to implement Serializable , by the way. They are typically using Java Reflection to inspect your class, so implementing the Serializable interface would be superflous — it would not add any useful information.

I have a separate tutorial about serializing and deserializing Java objects to and from JSON here: Java JSON Tutorial .

More Information About Serialization

Object serialization is kind of a topic in its own right. This Java IO tutorial is mostly focused on the streams and readers / writers. Therefore I will not get into deeper detail about object serialization at this point. In addition,a lot has already been written online about Java object serialization. Instead of repeating it, I’ll give you a link to deeper explanations of the subject.

Источник

Сериализация в Java

Сериализация это процесс сохранения состояния объекта в последовательность байт; десериализация это процесс восстановления объекта, из этих байт. Java Serialization API предоставляет стандартный механизм для создания сериализуемых объектов. В этой статье вы увидите как сериализовать объект, и почему сериализация иногда необходима. Вы узнаете об алгоритме сериализации используемом в Java и увидите пример, который иллюстрирует сериализованый формат объекта. В конце у вас должно сложиться чёткое представление о том, как работает алгоритм сериализации, а так же каким образом представлены части объекта в сериализованном виде.

Зачем сериализация нужна?

В сегодняшнем мире типичное промышленное приложение будет иметь множество компонентов и будет распространено через различные системы и сети. В Java всё представлено в виде объектов; Если двум компонентам Java необходимо общаться друг с другом, то им необходим механизм для обмена данными. Есть несколько способов реализовать этот механизм. Первый способ это разработать собственный протокол и передать объект. Это означает, что получатель должен знать протокол, используемый отправителем для воссоздания объекта, что усложняет разработку сторонних компонентов. Следовательно, должен быть универсальный и эффективный протокол передачи объектов между компонентами. Сериализация создана для этого, и компоненты Java используют этот протокол для передачи объектов.

Рисунок 1 демонстрирует высоко-уровневое представление клиент-серверной коммуникации, где объект передаётся с клиента на сервер посредством сериализации.

Рисунок 1.

Как сериализовать объект?

Для начала следует убедиться, что класс сериализуемого объекта реализует интерфейс java.io.Serializable как показано в листинге 1.

class TestSerial implements Serializable public byte version = 100;
public byte count = 0;
>

* This source code was highlighted with Source Code Highlighter .

В Листинге 1 только одна вещь отличается от создания нормального класса, это реализация интерфейса java.io.Serializable . Интерфейс Serializable это интерфейс-маркер; в нём не задекларировано ни одного метода. Но говорит сериализующему механизму, что класс может быть сериализован.

Теперь у нас есть всё необходимое для сериализации объекта, следующим шагом будет фактическая сериализация объекта. Она делается вызовом метода writeObject() класса java.io.ObjectOutputStream , как показано в листинге 2.

public static void main( String args[]) throws IOException FileOutputStream fos = new FileOutputStream( «temp.out» );
ObjectOutputStream oos = new ObjectOutputStream(fos);
TestSerial ts = new TestSerial();
oos.writeObject(ts);
oos.flush();
oos.close();
>

* This source code was highlighted with Source Code Highlighter .

В листинге 2 показано сохранение состояния экземпляра TestSerial в файл с именем temp.out

Для воссоздания объекта из файла, необходимо применить код из листинга 3.

public static void main( String args[]) throws IOException FileInputStream fis = new FileInputStream( «temp.out» );
ObjectInputStream oin = new ObjectInputStream(fis);
TestSerial ts = (TestSerial) oin.readObject();
System. out .println( «version gray»>* This source code was highlighted with Source Code Highlighter .

Восстановление объекта происходит с помощью вызова метода oin.readObject() . В методе происходит чтение набора байт из файла и создаие точной копии графа оригинального объекта. oin.readObject() может прочитать любой сериализованный объект, поэтому необходимо полученный объект приводить к конкретному типу.
Выполненный код выведет version=100 в стандартный вывод.

Формат сериализованного объекта

Как должен выглядеть сериализованный объект? Вспомните простой код из предыдущего раздела, который сериализует объект класса TestSerial и записывает в temp.out . В листинге 4 показано содержимое файла temp.out , в шестнадцатеричном виде.

AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65
73 74 A0 0C 34 00 FE B1 DD F9 02 00 02 42 00 05
63 6F 75 6E 74 42 00 07 76 65 72 73 69 6F 6E 78
70 00 64

Если вы снова посмотрите на TestSerial , то увидите, что у него всего 2 байтовых члена. Как показано в листинге 5.

public byte version = 100;
public byte count = 0;

* This source code was highlighted with Source Code Highlighter .

Размер байтовой переменной один байт, и следовательно полный размер объекта (без заголовка) — два байта. Но размер сериализованного объекта 51 байт. Удивлены? Откуда взялись эти дополнительные байты и что они обозначают? Они добавлены сериализующим алгоритмом и необходимы для воссоздания объекта. В следующем абзаце будет подробно описан этот алгоритм.

Алгоритм сериализации Java

К этому моменту у вас уже должно быть достаточно знаний, чтобы сериализовать объект. Но как работает этот механизм? Алгоритм сериализации делает следующие вещи:

  • запись метаданных о классе ассоциированном с объектом
  • рекурсивная запись описания суперклассов, до тех пор пока не будет достигнут java.lang.object
  • после окончания записи метаданных начинается запись фактических данных ассоциированных с экземпляром, только в этот раз начинается запись с самого верхнего суперкласса
  • рекурсивная запись данных ассоциированных с экземпляром начиная с самого низшего суперкласса

В листинге 6 указан пример охватывающий все возможные случаи сериализации

class parent implements Serializable int parentVersion = 10;
>

class contain implements Serializable int containVersion = 11;
>
public class SerialTest extends parent implements Serializable int version = 66;
contain con = new contain();

public int getVersion() return version;
>
public static void main( String args[]) throws IOException FileOutputStream fos = new FileOutputStream( «temp.out» );
ObjectOutputStream oos = new ObjectOutputStream(fos);
SerialTest st = new SerialTest();
oos.writeObject(st);
oos.flush();
oos.close();
>
>

* This source code was highlighted with Source Code Highlighter .

В примере сериализуется объект класса SerialTest , который наследуется от parent и содержит объект-контейнер класса contain . В листинге 7 показан сериализованный объект.

AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65
73 74 05 52 81 5A AC 66 02 F6 02 00 02 49 00 07
76 65 72 73 69 6F 6E 4C 00 03 63 6F 6E 74 00 09
4C 63 6F 6E 74 61 69 6E 3B 78 72 00 06 70 61 72
65 6E 74 0E DB D2 BD 85 EE 63 7A 02 00 01 49 00
0D 70 61 72 65 6E 74 56 65 72 73 69 6F 6E 78 70
00 00 00 0A 00 00 00 42 73 72 00 07 63 6F 6E 74
61 69 6E FC BB E6 0E FB CB 60 C7 02 00 01 49 00
0E 63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E 78
70 00 00 00 0B

На рисунке 2 показан сценарий алгоритма сериализации.

Рисунок 2.

  • AC ED: STREAM_MAGIC . Говорит о том, что используется протокол сериазизации.
  • 00 05: STREAM_VERSION . Версия сериализации.
  • 0x73: TC_OBJECT . Обозначение нового объекта.
  • 0x72: TC_CLASSDESC . Обозначение нового класса.
  • 00 0A : Длина имени класса.
  • 53 65 72 69 61 6c 54 65 73 74: SerialTest , имя класса.
  • 05 52 81 5A AC 66 02 F6: SerialVersionUID , идентификатор класса.
  • 0x02 : Различные флаги. Этот специфический флаг говорит о том, что объект поддерживает сериализацию.
  • 00 02 : Число полей в классе.
  • 0x49 : Код типа поля. 49 это «I», которое закреплено за Int.
  • 00 07 : Длина имени поля.
  • 76 65 72 73 69 6F 6E: version , имя поля.
  • 0x74: TC_STRING . Обозначает новую строку.
  • 00 09 : Длина строки.
  • 4C 63 6F 6E 74 61 69 6E 3B: Lcontain; , Каноническое JVM обозначаение.
  • 0x78: TC_ENDBLOCKDATA , Конец опционального блока данных для объекта.
  • 0x72: TC_CLASSDESC . Обозначение нового класса.
  • 00 06 : Длина имени класса.
  • 70 61 72 65 6E 74: parent , имя класса
  • 0E DB D2 BD 85 EE 63 7A: SerialVersionUID , идентификатор класса.
  • 0x02 : Различные флаги. Этот флаг обозначает что класс поддерживает сериализацию.
  • 00 01 : Число полей в классе.
  • 0x49 : Код типа поля. 49 обозначает «I», которое закреплено за Int.
  • 00 0D : Длина имени поля.
  • 70 61 72 65 6E 74 56 65 72 73 69 6F 6E : parentVersion, имя поля.
  • 0x78: TC_ENDBLOCKDATA , конец опционального блока данных для объекта.
  • 0x70: TC_NULL , обозначает то что больше нет суперклассов, потому что мы достигли верха иерархии классов.
  • 00 00 00 0A: 10 , Значение parentVersion .
  • 00 00 00 42: 66 , Значение version .

* This source code was highlighted with Source Code Highlighter .

  • 0x73: TC_OBJECT , обозначает новый объект.
  • 0x72: TC_CLASSDESC , обозначает новый класс.
  • 00 07 : Длина имени класса.
  • 63 6F 6E 74 61 69 6E: contain , имя класса.
  • FC BB E6 0E FB CB 60 C7: SerialVersionUID , идентификатор этого класса.
  • 0x02 : Различные флаги. Этот флаг обозначает что класс поддерживает сериализацию.
  • 00 01 : Число полей в классе.
  • 0x49 : Код типа поля. 49 обозначает «I», которое закреплено за Int.
  • 00 0E : Длина имени поля.
  • 63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E: containVersion , имя поля.
  • 0x78: TC_ENDBLOCKDATA , конец опционального блока данных для объекта.
  • 0x70: TC_NULL
  • 00 00 00 0B: 11 , значение containVersion .

Заключение

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

Об авторе

Sathiskumar Palaniappan имеет более чем 4-х летний опыт работы в IT-индестрии, и работает с Java технологиями более 3 лет. На данный момент он работает system software engineer в Java Technology Center, IBM Labs. Также имеет опыт работы в телекоммуникационной индустрии.

Источник

Читайте также:  Black Goose Bistro
Оцените статью