Search code examples
javaserializationserializable

java Serializable interface has no function, why it affects "writeObject"/"readObject"


I checked that the interface of

Serializable

Has no function definition, yet when I define

private void readObject(ObjectOutputStream oos){
    System.out.println("readObject!!");
}
private void writeObject(ObjectOutputStream oos){
    System.out.println("writeObject!!");
}

function in a class, they're called while object is being serialized.

This is odd to me, if the interface defines these 2 functions, then I should override them to make sure they're called.

But in Serializable, how does compiler generate code that if I define my own "writeObject"/"readObject", they're called while serialization?

I tried to append

@Override

annotation on top of both functions, compiler reports error.

So how it works at all, would you help to give some explanations?

Thanks a lot!


Solution

  • java.io.Serializable is a functional interface, so that means it doesn't define any methods in it. @Override annotation is put if only you really wanna make sure noone will try to modify your overridden method. The reason you got a compiler error on @Override is that there is no such method in Serializable, but instead you can find them in ObjectInputStream and ObjectOutputStream (which use as a low-level classes FileInputStream and FileOutputStream respectively). If you really wanna do Serialization on let's say, a list, you can do it like this:

    package Chaper8.IO;
    
    import java.io.*;
    
    import java.util.*;
    
    public class Serialization_Deserialization {
    
    public static void main(String [] args){
    
        /*
         *  try-catch with resources, JVM makes sure to close the resources after you've finished using it
         * much easier than using finally and getting an exception for each resource closed
         * 
         */
        try(FileOutputStream out = new FileOutputStream("C:\\Users\\Andrei\\Desktop\\Exemple\\worker.txt");
            ObjectOutputStream oos = new ObjectOutputStream(out);
    
            FileInputStream in = new FileInputStream("C:\\Users\\Andrei\\Desktop\\Exemple\\worker.txt");
            ObjectInputStream ois = new ObjectInputStream(in);){
    
            //instances of the Worker class
            Worker w1 = new Worker("Worker1", 123456 , 2000.5);
            Worker w2 = new Worker("Worker2", 765436, 1500.15);
            Worker w3 = new Worker("Worker3", 364582, 1700.45);
            Worker w4 = new Worker("Worker4", 878234, 2100.34);
            ArrayList<Worker> list = new ArrayList<>();
    
            //just adding the persons in the list
            list.add(w1);
            list.add(w2);
            list.add(w3);
            list.add(w4);
    
    
            System.out.println("Doing serialization");
            oos.writeObject(list);
    
            System.out.println("Doing deserialization");
            ois.readObject();
    
        }catch(IOException | ClassNotFoundException e){
                e.printStackTrace();
        }
    }
    } 
    

    Worker.java

    /*
     *  Worker class, basic type with variables, constructor, and toString() overridden
     *  Here I have implemented Serializable for the reason that I need to make sure that
     *  I will serialize the object within the class
     *
     *  Note that I used transient for id. transient is a special keyword which makes sure 
     * that id will not be serialized, used for security reasons.
     * 
     *  serialVersionUID is another variable which is used during deserialization 
     * to verify that the sender and receiver of a serialized object have loaded 
     * classes for that object that are compatible with respect to serialization. 
     *  Throws InvalidClassException if the object has a different serialVersionUID
     * than that of the corresponding sender's class.
     *  
     */
    
    import java.io.*;
    class Worker implements Serializable{
    
    private static final long serialVersionUID = 1L;
    private String name;
    private transient int id;
    private double wage;
    
    public Worker(String name, int id, double wage){
        this.name = name;
        this.id = id;
        this.wage = wage;
    }
    public String toString(){
        return "Person with name " +
        name + " and with id " +
        id + " has a salary of " + wage + "$";
        }
    }