Wouter Vandenputte
Wouter Vandenputte

Reputation: 2103

Java serialization extension of class

suppose i have a class Article

public class Article implements Serializable
{
   private static final long serialVersionUID = 1420672609912364060L;
   private String title;
   private String text;
   private UUID uid;

   public Article(){ //empty default constructor
   }

   // Getters and setters 
   ...  
}

and I serialize multiple instances of it using the following code

public void save(Article article)
{
    FileOutputStream fos = null;
    try {
        fos = context.openFileOutput("article_"+ article.getUid(), Context.MODE_PRIVATE);
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(article);
        os.close();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

I then later extend the class making it look like this:

public class Article implements Serializable
{
   private static final long serialVersionUID = 1420672609912364060L;
   private String title;
   private String text;
   private Person author;
   private UUID uid;

   public Article(){
       author = Person.UNKNOWN;
   }

   // Getters and setters 
   ...
}

Then when I load it in, why is author null? I always thought the default constructor was called and then the setter for every found property, but putting a breakpoint in the default constructor and then debugging shows it isn't called. Meaning that for the old Article class, the author would simply be null instead of Person.UNKNOWN. The class Person itself is also serializable.

This is my loading in code if it might be relevant.

private Article loadArticle(String fileName)
{
    FileInputStream fis = null;
    try {
        fis = context.openFileInput(fileName);
        ObjectInputStream is = new ObjectInputStream(fis);
        Article article = (Article ) is.readObject();
        is.close();
        fis.close();
        return article;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (InvalidClassException e) {
    }
    catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return null;
}

Note that is all Android configuration

Upvotes: 2

Views: 211

Answers (2)

Dorian Gray
Dorian Gray

Reputation: 2981

No, the default constructor is not called - it just sets every field, that has not been found in the serialized data, to 0.

You can manually set custom fields on deserialisation like that:

public class Article implements Serializable {
   private static final long serialVersionUID = 1420672609912364060L;
   private String title;
   private String text;
   private transient Person author;
   private UUID uid;

   public Article(){
       author = Person.UNKNOWN;
   }

   /**
    * Called upon deserialisation
    */
   private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
       // read non transient fields
       in.defaultReadObject();
       author = Person.UNKNOWN;
   }

   // Getters and setters 
   ...
}

Upvotes: 0

m.antkowicz
m.antkowicz

Reputation: 13571

I always thought the default constructor was called

Nope it wasn't. Take a look at the documentation

During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream.

Upvotes: 3

Related Questions