Skip to content
Aleksandr Kuchuk edited this page May 12, 2016 · 29 revisions

###Examples: All examples in module code-examples in package serialization. ##Binary Serialization

About

A lot of people think that serialization is quite simple - all that we do is implement java.io.Serializable interface.

Yes, in simple - it's all that we need, but what about different finer points? How many ways are there to serialize object? One? Two? The right answer is - two ways! We can:

  • implements java.io.Serializable
  • implements Externalizable

Let's talk about it more detail!

Serializable interface

Standart serialization in Java works through Reflection API, class puzzles out for the fields and writes to the output. And ofcourse if we use reflection - it's not optimal. And another one - when we use standart serialization we don't call constructor of the class in deserialization, we reserve memory for the class and after that all class fields fill by values from stream(input). We don't call constructor!

And what about parent class? If our class is serializable, what about parent class? Parent class isn't serializable! When we deserialize our class - we call constructor without parameters! And we don't call constructor of class which we try to deserialize. If we haven't got this constructor - we catch an error. After our example in code - we have class with parameter i which we recieve after deserialization and other parameters create default constructor.

And another one interesting moment: We implement Serializable interface and put two methods to our class:

 private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException;
 private void writeObject(java.io.ObjectOutputStream stream) throws IOException;
 private void readObjectNoData() throws ObjectStreamException;

And when we serialize our object - java calls these methods! But we should implement these methods only if we want special handling during the serialization and deserialization process.

In writeObject, for example:

private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject(); // default serialization
//our special serialization
}

In readObject, for example:

private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject(); // default deserialization
//our special deserialization and using setters
}

To sum up:

  • If our parent class is Serializable - all children are serializable.
  • If child class is Serializable, but parent isn't - parent's fileds initialize by default constructor.
  • java.io.Serializable - is a mark, label, all classes which we want to serialize should implement it.
  • We can use special handling during serialization and deserialization - just implement special methods in class.
  • In Serialization process: our class metadata, parent metadata, patent data , our class data.
  • In Deserialization process: parent metadata, our class metadata, our class data, parent data.
  • If we have non-Serializable field in class and this field isn't null - we have a problem and exception.

Externalizable interface

Another approach!

Instead of java.io.Serializable this interface contains two methods – writeExternal(ObjectOutput) and readExternal(ObjectInput). All logic of serialization and deserialization is here. We don't write any metadata of parent classes!

We only call implplemented method - and this method serialize out class as we want. It's very flexible way. And often we write less information than when we use first way. Cause we don't write metadata, meta information!

How it works? First of all we call default constructor. And that is why we MUST have public default constructor. All children should have it too. After that on new object of our class we call methods(readExternal) and all our fields are filling data. If field is transient - it should have default value.

To sum up:

  • If we implement both interfaces - Externalizable and Serializable - the Externalizable has high priority.
  • Externalizable is more flexible.
  • Externalizable has a good gain in terms of the serialized data.

Remarks

And it's important to say:

  • Static fields doesn't serialize in standart approach, but in theory we can(don't do it!) serialize it by Externalizable.
  • We can't deserialize final fields of class - cause we use consrtuctor.
  • After deserialization we MUST check our object for correctness - and throw java.io.InvalidObjectException. if our object is wrong. *And we have difficulties when we want to serialzie/deserialize Singleton object.

Serial Version UID

Why we have private static final long serialVersionUID? This field contains unique id version of serizalization class. It calculates by fields, order of field declaring, methods and etc. And if we change class state - we change this id. And this field writes to the serialization stream, when we deserialize our object we compare ids and if anything is wrong - throw exception. Java strongly recommended to declare this field. It's your guarantee that all process was correct.

##XML Serialization

About

We can use another serialization in java - just serialize our object in xml. It's not binary serialization. How we can do it?

JAXB

Java Architecture for XML Binding.

With this approach we can use XML-schema(XSD)and match our Java object with XML-documents. It's also known as marshalling and demarshalling processes. JAXB can generate XSD, validate schemes. And it's configure with Annotations.

JAXB in Java SE and it's another plus.

  • First of all we should annotate like @XmlRootElement the main, root, element. We can have only one root element.
  • Secondly we should annotate accessor type - @XmlAccessorType(XmlAccessType.____) - replace ___ as you want, for example put - XmlAccessType.NONE.

A little bit more information about it:

  • XmlAccessType.NONE - We save only annotated elements(fields).
  • XmlAccessType.FILED - We save all fields but whithout static and transient fields.
  • XmlAccessType.PROPERTY - All getters/setters pairs and annotated fields.
  • XmlAccessType.PUBLIC - All public fields and annotated fields.

I think thats all clear. Let's continue.

  • After that annotate all fields which you want by @XmlElement. It's not neccessary that your field have getters and setters. Cause we use Reflection.

If we have collections - we can use XmlElementWrapper annotation. It's all simple and you can see examples in code. JAXB has a lot of annotations, which can help you to save your object as you want, for example, you can set the order of writing fields in xml and etc.

##JSON Serialization JSON is very good choice cause it has a good syntax, a lot of libs, small size. In this example we would use library GSON .

Why GSON?

  • Good speed when we work with large data.
  • Wokr whithout annotatioans and metadata. We simply can say - i want this object convert to JSON.
  • We can handle order of dumping.
  • Work with null.
  • Simple to use and work.

It's very good choice, simple and powerful, without annotatioans and metadata. Just try it.

Clone this wiki locally