Java. Serialization of objects. The transient keyword. Examples




Serialization of objects. The transient keyword. Examples


Contents


Пошук на інших ресурсах:

1. What is serialization? Advantages of serialization

The Java programming language has powerful facilities for providing a serialization mechanism. Serialization is the ability of an object to save its own data (object state) in a byte stream in order to further restore this data (state) during the next program starts. In other words, the current values of internal variables in an object can be saved (for example, to a file), and then restored at the right time.

The serialization mechanism provides the following benefits:

  • the object to be serialized exists between program runs. This mechanism is called lightweight persistence. The object is first saved to disk, then restored to its initial state the next time the program is started;
  • provides remote invocation of Java methods, which allows you to work with objects that are “located” on remote computers as if they existed on your computer;
  • the need to save the current information about the state of the visual JavaBeans;
  • use in objects of classes that require maintaining the current state.

 

2. Implementing Serialization in Java Programs

In the Java language, in order to serialize an object in a program, you need to adhere to the following recommendations. All classes related to serialization must implement the Serializable interface. This means that the class that implements serialization should look something like this:

class MySerializeClass implements Serializable {
  ...
}

so the class, the instance of which is serialized, must also implement the Serializable interface:

class MyDataClass implements Serializable {
  ...
}

 

2.1. Writing an object to a file

If a dataObj object of some DataClass class is created, then to save this object you need to perform the following actions.

1. Create a source stream fOut of type OutputStream. If the object is saved to a file, an initial stream of type FileOutputStream is created

FileOutputStream fOut = new FileOutputStream(filename);

where filename is the name of the file where the object will be saved.

The FileOutputStream class is a subclass of the abstract OutputStream class.

2. Pack fOut file object to another object type ObjectOutputStream

ObjectOutputStream objOut = new ObjectOutputStream(fOut);

The result is a stream of objOut.

3. Write an instance of dataObj to the objOut stream. For this, the built-in writeObject() method is used.

objOut.writeObject(dataObj);

4. Close both created streams

objOut.close();
fOut.close();

 

2.2. Reading an object from a file

If the object was previously saved, then in order to restore its state from the file, you need to perform the following steps.

1. Create an instance of fInput of the FileInputStream class

FileInputStream fInput = new FileInputStream(filename);

where filename is the name of the file (type String) in which the object was previously saved.

2. Create an instance of objInput of the ObjectInputStream class, into which to wrap the fInput instance of the FileInputStream class

ObjectInputStream objInput = new ObjectInputStream(fInput);

3. Read an instance using the readObject() method. For example, if you need to read an instance of the DataClass class, then the reading code will be as follows

DataClass dObj = (DataClass)objInput.readObject();

4. Close streams fInput and objInput

objInput.close();
fInput.close();

 

3. What is the purpose of the transient modifier?

The transient modifier is used when it becomes necessary to save an object (instance) of a class (to perform serialization). The transient modifier is set before the declaration of an internal class variable, the value of which should not be stored if the object is saved. Using the transient modifier, you can programmatically specify data that does not need to be saved when the object is serialized.

For example. In the following Book class, the price variable is declared with the transient modifier. This means that when writing to a file of any instance of the Book class, the values of the title, author, year variables will be written, except for the price variable.

class Book {
  String title;
  String author;
  int year;
  transient double price; // This variable will not be saved
}

 

4. An example of serializing and using the transient modifier. Classes ObjectInputStream and ObjectOutputStream

The example declares two classes:

  • the DataClass containing the data to be stored. An instance of this class is saved;
  • the SerializeClass class, which contains methods for writing an instance of the DataClass type. Both classes implement the Serializable interface.

The DataClass class declares:

  • internal variables a, b. The variable b is declared as a transient variable. This means that when writing an instance of the DataClass type to a file, the value of the b variable will not be written;
  • constructor DataClass(int, int);
  • methods for access to internal variables GetA(), GetB(), SetA(), SetB();
  • the Print() method, which outputs the value of internal variables.

The SerializeClass class declares:

  • the SaveData() method, which implements writing an instance of the DataClass type to a file;
  • the ReadData() method, which returns an instance of the DataClass type that was previously written to the file.
// Serialization of objects

import java.io.*;

// The class, the instance of which will need to be written/read from the file
class DataClass implements Serializable {
  // Internal variables
  private int a;
  private transient int b; // this variable will not be saved

  // Constructor
  DataClass(int a, int b) {
    this.a = a;
    this.b = b;
  }

  // Access methods
  int GetA() {
    return a;
  }

  int GetB() {
    return b;
  }

  void SetA(int a) {
    this.a = a;
  }

  void SetB(int b) {
    this.b = b;
  }

  // Method that outputs data
  void Print() {
    System.out.println("a = " + a + ",   b = " + b);
  }
}

// A class that contains methods for serializing (writing/reading data) of the DataClass
public class SerializeClass implements Serializable {

  // A method that writes an instance of the DataClass class to the file filename
  static void SaveData(DataClass dataObj, String filename)
      throws ClassNotFoundException, IOException {

    // 1. Create an instance of the FileOutputStream class - create a file stream
    FileOutputStream fOut = new FileOutputStream(filename);

    // 2. Create an instance of objOut of the ObjectOutputStream class - a stream of writing objects
    ObjectOutputStream objOut = new ObjectOutputStream(fOut);

    // 3. Write a dataObj instance to the objOut stream
    // 3.1. Write a comment
    objOut.writeObject("Storage the dataObj instance\n");

    // 3.2. Write instance
    objOut.writeObject(dataObj);

    // 4. Close the objOut stream
    objOut.close();

    // 5. Close the fOut stream
    fOut.close();
  }

  static DataClass ReadData(String filename)
      throws ClassNotFoundException, IOException {

    // 1. Create an instance of FileInputStream class
    FileInputStream fInput = new FileInputStream(filename);

    // 2. Create an instance of ObjectInputStream class
    ObjectInputStream objInput = new ObjectInputStream(fInput);

    // 3. Read data from the file named filename to dataObj instance
    // 3.1. Read the comment
    String s = (String)objInput.readObject();

    // 3.2. Read the instance of DataClass class
    DataClass dObj = (DataClass)objInput.readObject();

    // 4. Close streams
    objInput.close();
    fInput.close();

    // 5. Return the result
    return dObj;
  }

  public static void main(String[] args) 
      throws ClassNotFoundException, IOException {

    // 1. Write the instance of DataClass class to "myFile.dat" file
    // 1.1. Create an object of DataClass class
    DataClass objData = new DataClass(5, 8);

    // 1.2. Write object objData to "myFile.dat" file
    SaveData(objData, "myFile.dat");

    // 2. Read the instance of DataClass from file "myFile.dat"
    // 2.1. Declare the reference to DataClass
    DataClass objData2;

    // 2.2. Read data to objData2
    objData2 = ReadData("myFile.dat");

    // 2.3. Print data
    objData2.Print(); // a = 5,   b = 0 - the value of the variable b was not written
  }
}

 

5. Are class methods saved during serialization?

No. When using the serialization mechanism, only data (internal variables) are saved.

 

6. An example of a class that contains methods for serializing an instance of this class

In the example, the Sphere class is developed, in which the methods are defined:

  • writing to the file of the current instance of the class;
  • reading data from the file of the current class.

The class contains methods for serializing an instance of this class.

The class text is as follows

// A class containing methods for serializing an object of this class

import java.io.*;

class Sphere implements Serializable {

  // Internal variable - the radius of a sphere
  private double radius;

  // Access methods
  public double GetR() {
    return radius;
  }

  public void SetR(double radius) {
    this.radius = radius;
  }

  // Methods for serializing an object of this class
  public void SaveToFile(String filename)
      throws ClassNotFoundException, IOException      {

    // 1. Create an instance of FileOutputStream class - create file stream
    FileOutputStream fOut = new FileOutputStream(filename);

    // 2. Create instance objOut of class ObjectOutputStream - objects write stream
    ObjectOutputStream objOut = new ObjectOutputStream(fOut);

    // 3. Write the current instance to the objOut stream
    objOut.writeObject(this);

    // 4. Close the objOut stream
    objOut.close();

    // 5. Close the file stream
    fOut.close();
  }

  public Sphere ReadFromFile(String filename)
      throws ClassNotFoundException, IOException {

    // 1. Create an instance of FileInputStream class
    FileInputStream fInput = new FileInputStream(filename);

    // 2. Create an instance of ObjectInputStream class
    ObjectInputStream objInput = new ObjectInputStream(fInput);

    // 3. Read data from filename to insnance dObj
    Sphere dObj = (Sphere)objInput.readObject();

    // 4. Close streams
    objInput.close();
    fInput.close();

    // 5. Return the result
    return dObj;
  }

  // Method of calculating the volume of a sphere
  public double Volume() {
    if (radius > 0)
      return 4.0 / 3.0 * Math.PI*radius*radius*radius;
    return 0.0;
  }
}

public class DemoSerialization implements Serializable {

  public static void main(String[] args)
      throws ClassNotFoundException, IOException {

    // 1. Write the instance of class Sphere to the "myfile.dat" file
    // 1.1. Create an instance sp
    Sphere sp = new Sphere();

    // 1.2. Set the radius
    sp.SetR(25.5);

    // 1.3. Write sp to the file
    sp.SaveToFile("myfile.dat");

    // 2. Read a previously written instance from a file
    // 2.1. Declare a new instance sp2 of type Sphere
    Sphere sp2 = new Sphere();

    // 2.2. Read sp2
    sp2 = sp2.ReadFromFile("myfile.dat");

    // 2.3. Print the value in sp2
    System.out.println("sp2.radius = " + sp2.GetR());
  }
}

The result of the program

sp2.radius = 25.5

 


Related topics