Home > JAVA > Java learning note – Serialization 01

Java learning note – Serialization 01

With serialization we can stream our Java object to a sequence of byte and restore these objects from this stream of bytes. To make a Java object serializable you implement the java.io.Serializable interface. This is only a marker interface which tells the Java platform that the object is serializable.

Classes ObjectInputStream and ObjectOutputStream are high-level streams that contain the methods for serializing and deserializing an object, usually we wrap them arround lower-level classes FileOutputStream. The magic happens with just two methods:
ObjectOutputStream.writeObject(); – for serialize object
ObjectInputStream.readObject(); – for deserialize object

Person.java


public class Person implements Serializable
{
private static final long serialVersionUID = -2344139368896541663L;

private String firstName;
private String lastName;
private int age;

public Person() {

}

public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

App.java


public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
Person person = new Person();
person.setFirstName("Foo");
person.setLastName("Fooo");
person.setAge(29);

try {
FileOutputStream fs = new FileOutputStream("tesSerialize.txt");
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(person);
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

try {
FileInputStream fin = new FileInputStream("tesSerialize.txt");
ObjectInputStream in = new ObjectInputStream(fin);
Person person2 = (Person) in.readObject();
in.close();
System.out.print("Hai " + person2.getFirstName() + " " + person2.getLastName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

When we run:
Result

What is serialVersionUID?

serialVersionUID is used to ensure that same class(that was used during Serialization) is loaded during deserialization. serialVersionUID is used for version control of object. We should change serialVersionUID when there is some change in the definition of data stored in the class for example data type of field is changed.

What if we have reference to another object?

When we serialize object and if it contain any other object reference then Java serialization serialize that object’s entire object graph. For example if our Person object has a reference to Address object and Address object can have reference to another object then when we serialize Person all other object reference such as Address will be automatically serialized.

Address.java


public class Address implements Serializable{

private static final long serialVersionUID = 2593208850669123663L;

private String streetName;
private String homeNo;

public Address() {

}

public Address(String homeNo, String streetName) {
this.homeNo = homeNo;
this.streetName = streetName;
}

public String getHomeNo() {
return homeNo;
}

public void setHomeNo(String homeNo) {
this.homeNo = homeNo;
}

public String getStreetName() {
return streetName;
}

public void setStreetName(String streetName) {
this.streetName = streetName;
}
}

Person.java


public class Person implements Serializable
{
private static final long serialVersionUID = -2344139368896541663L;

private String firstName;
private String lastName;
private int age;
private Address address;

public Person() {

}

public Person(String firstName, String lastName, int age, Address address) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.address = address;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
}
}

App.java


public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
Address address = new Address();
address.setStreetName("Street one");
address.setHomeNo("10");

Person person = new Person();
person.setFirstName("Foo");
person.setLastName("Fooo");
person.setAge(29);
person.setAddress(address);

try {
FileOutputStream fs = new FileOutputStream("tesSerialize.txt");
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(person);
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

try {
FileInputStream fin = new FileInputStream("tesSerialize.txt");
ObjectInputStream in = new ObjectInputStream(fin);
Person person2 = (Person) in.readObject();
in.close();
System.out.print("Hai " + person2.getFirstName() + " " + person2.getLastName() + " your street name: " + person.getAddress().getStreetName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

When we run:
Result

 

Important things to remember, Address class must also implement Serializable interface. If not, we will got java.io.NotSerializableException.

But what would happen if we didn’t have access to the Address class source code? In other words, what if making the Address class implement Serializable interface was not an option?
We can mark Address object with transient, then serialization will skip the Address object during serialization. In other words, when Person is deserialized, it comes back with a null Address.But what if we still want to have same state as when we have serialized address object. Java serialization provides a mechnism such that if we have private methods with particular signature then they will get called during serialization and deserialization. The two special methods we define must have signatures that exactly like this:

private void writeObject (ObjectOutputStream os) { }
private void readObject (ObjectInputStream is) { }

 

 

Person class after we use this two special method


public class Person implements Serializable
{
 private static final long serialVersionUID = -2344139368896541663L;

private String firstName;
 private String lastName;
 private int age;
 transient private Address address;

public Person() {

}

public Person(String firstName, String lastName, int age, Address address) {
 this.firstName = firstName;
 this.lastName = lastName;
 this.age = age;
 this.address = address;
 }

private void writeObject (ObjectOutputStream os) {
 try {
 os.defaultWriteObject();
 os.writeObject(address.getStreetName());
 os.writeObject(address.getHomeNo());
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 private void readObject (ObjectInputStream is) {
 try {
 is.defaultReadObject();
 String addressStreetName = (String) is.readObject();
 String addressHomeNo = (String) is.readObject();
 address = new Address(addressHomeNo, addressStreetName);
 } catch (IOException e) {
 e.printStackTrace();
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 }
 }

//ommit setter-getter for simplicity

}

 

 

The important things should be kept in mind that ObjectInputStream should read data in same sequence in which we have written data to ObjectOutputStream.

When we want to do only a part of the serialization/deserialization by ourself, we must invoke the defaultWriteObject() and defaultReadObject() method to do the rest.

Categories: JAVA
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: