2016-11-29 3 views
0

Отказ от ответственности - это часть школьного семестрового проекта.Memento pattern in Java - сериализация внутреннего класса

Для сохранения состояния объекта мы должны использовать шаблон Memento. Этот объект является моделью в MVC. Так как у меня теперь есть (упрощенно):

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 
    } 
} 

Я прочитал, что, имея Serializable внутреннего класса в то время как внешний класс не являешься на самом деле не возможно в Java по разумным причинам. НО, в моем случае мне не нужен внешний класс, который будет создан, когда будет внутренний. Внутреннему вообще не нужно внешнее. Он только структурирован таким образом, чтобы внешний класс мог получить доступ к внутренним членам.

Это то, что говорит описание Memento моего курса в:

enter image description here

... и это имеет смысл, а также. Только модель должна иметь доступ к деталям внутри Memento. Объект «Caretaker» (обработка объекта, сохраняющая/извлекающую данные на диск) не должна находиться внутри объекта. Поскольку Java не имеет классов друзей, это должен быть путь.

Означает ли это, что для его реализации, как предложено, я не могу использовать сериализацию?

Edit:

Я сделал Memento класс статичен, а также класс статистики, но я все еще получаю ошибку. Кажется, что до сих пор существует this ссылки в 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", [email protected]) 
    - 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", [email protected]) 
+0

В вашем классе 'Model' или его внутреннем классе' Stats' есть члены или (анонимные) внутренние классы, содержащие ссылки на объекты, которые не являются сериализуемыми. – Jesper

ответ

0

Экземпляра нестатического внутреннего класса имеет скрытую ссылку на экземпляр своего внешнего класса. Это означает, что если вы собираетесь сериализовать экземпляр внутреннего класса, экземпляр внешнего класса будет сериализован вместе с ним. Если внешний класс не является сериализуемым, вы получите java.io.NotSerializableException.

Если вы не хотите, чтобы экземпляр внешнего класса сериализовать вместе с экземпляром внутреннего класса, а затем сделать внутренний класс static:

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

static внутренний класс не имеет ссылка на экземпляр его внешнего класса.

+0

(..я я был в середине написания комментария ..) Термин статический смутил меня, и только до сих пор я действительно искал, что означает «вложенный статический класс». Оказывается, он не является статичным в смысле «статического члена», «статического метода» или даже статического класса, подобного C#. Тем не менее, я все еще получаю исключение NotSerializableException. Посмотрите отредактированный вопрос. –

+0

Сериализуемость «заразная». Типы всех переменных-членов 'Memento' также должны быть сериализуемыми. Например, «ModelData» также должен быть сериализуемым, и все типы, к которым относится «ModelData», тоже должны быть такими и т. Д. – Jesper

+0

Часто лучше не использовать сериализацию Java, а использовать другой механизм для хранения состояния объекта, предпочтительно основанный на хорошо известном стандартном формате, таком как JSON или XML. Сериализация Java использует сложный для понимания двоичный формат и очень сильно привязан к исходному коду (добавьте переменную-член, и вы больше не можете читать старые сериализованные объекты). – Jesper

Смежные вопросы