Java Language Sérialisation personnalisée


Exemple

Dans cet exemple, nous voulons créer une classe qui générera et sortira en console, un nombre aléatoire compris entre une plage de deux nombres entiers qui seront transmis en tant qu’arguments lors de l’initialisation.

    public class SimpleRangeRandom implements Runnable {
    private int min;
    private int max;

    private Thread thread;

    public SimpleRangeRandom(int min, int max){
        this.min = min;
        this.max = max;
        thread = new Thread(this);
        thread.start();
    }

    @Override
 private void WriteObject(ObjectOutputStreamout) throws IO Exception;
    private void ReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
    public void run() {
        while(true) {
            Random rand = new Random();
            System.out.println("Thread: " + thread.getId() + " Random:" + rand.nextInt(max - min));
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    }

Maintenant, si nous voulons rendre cette classe sérialisable, il y aura des problèmes. Le thread est l'une des classes de niveau système qui ne sont pas Serializable. Nous devons donc déclarer le thread comme transitoire . En faisant cela, nous serons en mesure de sérialiser les objets de cette classe mais nous aurons toujours un problème. Comme vous pouvez le voir dans le constructeur, nous définissons les valeurs min et max de notre randomiseur et ensuite nous démarrons le thread qui est responsable de la génération et de l'impression de la valeur aléatoire. Ainsi, lors de la restauration de l'objet persistant en appelant le readObject (), le constructeur ne sera plus exécuté car il n'y a pas de création d'un nouvel objet. Dans ce cas, nous devons développer une sérialisation personnalisée en fournissant deux méthodes à l'intérieur de la classe. Ces méthodes sont:

private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

Ainsi, en ajoutant notre implémentation dans readObject (), nous pouvons lancer et démarrer notre thread:

class RangeRandom implements Serializable, Runnable {

private int min;
private int max;

private transient Thread thread;
//transient should be any field that either cannot be serialized e.g Thread or any field you do not want serialized

public RangeRandom(int min, int max){
    this.min = min;
    this.max = max;
    thread = new Thread(this);
    thread.start();
}

@Override
public void run() {
    while(true) {
        Random rand = new Random();
        System.out.println("Thread: " + thread.getId() + " Random:" + rand.nextInt(max - min));
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.defaultWriteObject();
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    in.defaultReadObject();
    thread = new Thread(this);
    thread.start();
}
}

Voici le principal pour notre exemple:

public class Main {
public static void main(String[] args) {
    System.out.println("Hello");
    RangeRandom rangeRandom = new RangeRandom(1,10);

    FileOutputStream fos = null;
    ObjectOutputStream out = null;
    try
    {
        fos = new FileOutputStream("test");
        out = new ObjectOutputStream(fos);
        out.writeObject(rangeRandom);
        out.close();
    }
    catch(IOException ex)
    {
        ex.printStackTrace();
    }


    RangeRandom rangeRandom2 = null;
       FileInputStream fis = null;
       ObjectInputStream in = null;
       try
       {
             fis = new FileInputStream("test");
             in = new ObjectInputStream(fis);
           rangeRandom2 = (RangeRandom)in.readObject();
             in.close();
           }
       catch(IOException ex)
       {
             ex.printStackTrace();
           }
       catch(ClassNotFoundException ex)
       {
             ex.printStackTrace();
           }

}
}

Si vous exécutez la commande principale, vous verrez qu'il y a deux threads en cours d'exécution pour chaque instance RangeRandom, car la méthode Thread.start () se trouve maintenant à la fois dans le constructeur et dans readObject () .