Search code examples
javaserializationdeserializationmarshallingunmarshalling

Why does my "marshaller" have to be "static"?


I'm trying to "marshall" and "unmarshall" objects, in their own class, and using a "Marshaller".

The Main method :

public class Main {

    public static void main(String[] args) {
        new Something();        
    }
}

The "Something" class that will produce the instances to marshall or unmarshall :

import java.io.File;
import java.io.Serializable;

public class Something implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    public int value = 2;
    private File file = new File("something.serial");
    private static Marshaller marshaller = new Marshaller();

    Something() {

        value = 3;
        marshaller.marshalling(file, this);
        Something anotherThing = (Something) marshaller.unmarshalling(file);
        System.out.println(anotherThing.value);
    }
}

Here is the Marshaller :

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Marshaller {

    public Marshaller() {

}

    /**
     * Charge l'objet sérializé d'un fichier si il existe
     * @param file : le fichier à désérialiser
     * @return obj : l'instance d'objet désérialisé
     */
    public Object unmarshalling(File file) {
        Object obj = null;
        ObjectInputStream ois;
        try {
            BufferedInputStream bis = new BufferedInputStream(
            new FileInputStream(file));
            ois = new ObjectInputStream(bis);
            obj = ois.readObject();
            ois.close();
        } catch(FileNotFoundException e) {
            e.printStackTrace();
        } catch(IOException e) {
            e.printStackTrace();
        } catch(ClassNotFoundException e) {
            e.printStackTrace();
        }
        return obj;
    }

    /**
     * Permet d'enregistrer un objet (settings, client...) dans un fichier
     * @param file : le fichier support de la sérialisation
     * @param obj : l'instance d'objet à sérialiser
     * 
     */
    public void marshalling(File file, Object obj) {
        ObjectOutputStream oos;
        try {
            oos = new ObjectOutputStream(
            new BufferedOutputStream(
            new FileOutputStream(file)));
            oos.writeObject(obj);
            oos.close();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

In the class Something, if my Marshaller isn't declared "static", I get a java.io.NotSerializableException. Why ?

Thank you for your answers to help me to understand.

Have a good day.

PS : Shall I use the word marshall or serialize ?


Solution

  • When you serialize an object, all of the objects that are reachable from that object are stored as well, so all of them must be serializable. If you declare your class like:

    public class Something implements Serializable {
        private static final long serialVersionUID = 1L;
        public int value = 2;
        private File file = new File("something.serial");
        private Marshaller marshaller = new Marshaller();
    }
    

    Then reachable fields from any instance of class Something are value, file and marshaller, so jvm will try to serialize them as well, which requires each of them must be serializable, but class Marshaller is not, then exception happens.

    When you declare a field as static, you make it a member of the class, not individual instance, since serialization only cares about the current state of instances, only data associated with a specific instance will be serilized, therefore all static fields are ignored and your program works OK.

    If you do need a field be instance member but don't want it to be serialized, you need to declare it with keyword transient, then it'll be ignored during the serialization.

    And for the word marshall and serialize, I'm not a native English speaker so I cann't tell too much about the difference between them, but personally I prefer serialize in this case, and use marshall when dealing JSON/XML from/to java objects.

    Hope this could be helpful to you :-)