0

Disclaimer - this is a part of a school semester project.

We should be using Memento pattern to save an object state. This object is a model in MVC. So the way I have it now is (simplified):

public class Model {
   // ...
   public static class Memento implements Serializable {
      protected Stats stats;

      public Memento(Stats stats) {
          this.stats = stats;
      }
   }

   public static class Stats implements Serializable {
           protected int score;
           protected int cannonPos;
           protected int cannonAngle;
           protected int cannonSpeed;
           protected int totalShotsFired = 0;
           protected int enemiesHit;
           protected transient List<StatsObserver> observers = new ArrayList<StatsObserver>();
           // + getters etc
   }
}

I have read that having a Serializable inner class whilst the outer class is not is not really possible in Java for reasonable reasons. BUT, in my case I do not need the outer class to be instantiated when the inner one is. Inner does not need outer at all. It is only structured like this so that the outer class can access the inner's members.

This is what my course's Memento description says:

enter image description here

... and that makes sense as well. Only the Model should be able to access the details inside Memento. The "Caretaker" object (an object handling saving/retrieving the data to/from disk) should not see inside the object. Since Java does not have friend classes, this should be the way to go.

Does it mean that in order to implement it as suggested I cannot use Serialization?

Edit:

I made Memento class static, as well as Stats class, but I am still getting the error. It seems that there still is a this reference in Model.Stats

java.io.NotSerializableException: cz.melkamar.adp.shooter.model.Model
    - field (class "cz.melkamar.adp.shooter.model.Model$Stats", name: "this$0", type: "class cz.melkamar.adp.shooter.model.Model")
    - object (class "cz.melkamar.adp.shooter.model.Model$Stats", cz.melkamar.adp.shooter.model.Model$Stats@de1a1b8)
    - field (class "cz.melkamar.adp.shooter.model.Model$Memento", name: "stats", type: "class cz.melkamar.adp.shooter.model.Model$Stats")
    - root object (class "cz.melkamar.adp.shooter.model.Model$Memento", cz.melkamar.adp.shooter.model.Model$Memento@1e920c72)
Martin Melka
  • 7,177
  • 16
  • 79
  • 138
  • Your class `Model`, or its inner class `Stats`, has members or (anonymous) inner classes that hold references to objects that are not serializable. – Jesper Nov 29 '16 at 14:50

1 Answers1

0

An instance of a non-static inner class has a hidden reference to an instance of its outer class. This means that if you are going to serialize the instance of the inner class, the instance of the outer class is going to be serialized along with it. If the outer class is not serializable, you'll get a java.io.NotSerializableException.

If you don't want the instance of the outer class to be serialized along with the instance of the inner class, then make the inner class static:

public class Model {
   // ...
   public static class Memento implements Serializable {
       protected ModelData data;
       // ...
   }
}

A static inner class does not have a reference to an instance of its outer class.

Jesper
  • 202,709
  • 46
  • 318
  • 350
  • (..as I was in the middle of writing a comment..) The term static confused me and it wasn't until now that I actually looked up what "nested static class" means. Turns out it's not static in the sense of a "static member", "static method" or even C#-like static class. I am still getting a NotSerializableException, though. Have a look at the edited question please. – Martin Melka Nov 29 '16 at 14:41
  • Serializability is "contagious". The types of all member variables of `Memento` must also be serializable. For example, `ModelData` must also be serializable, and all types that `ModelData` refers to must be so too, etc. – Jesper Nov 29 '16 at 14:44
  • Often it is better to not use Java serialization, but to use a different mechanism to store object state, preferrably based on a well-known standard format such as JSON or XML. Java serialization uses a hard to understand binary format and is tied to source code very tightly (add a member variable and you can't read old serialized objects anymore). – Jesper Nov 29 '16 at 14:47
  • I think I will end up going that way, it is better for by-hand debugging. I am trying to get a hold of this though. No members of the `Stats` class (previously noted as ModelData) should have any problems - they are just primitive types. – Martin Melka Nov 29 '16 at 14:49
  • What does class `Stats` look like? Does it have an anonymous inner class? – Jesper Nov 29 '16 at 14:52
  • Stats: http://hastebin.com/sekuledofo.java .. There are no anonymous classes, it is simply a data object. – Martin Melka Nov 29 '16 at 15:03