【问题标题】:Memento pattern in Java - serialization of inner classJava中的Memento模式——内部类的序列化
【发布时间】:2017-04-13 13:46:07
【问题描述】:

免责声明 - 这是学校学期项目的一部分。

我们应该使用 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
   }
}

我已经读到,出于合理的原因,在 Java 中实际上不可能有一个可序列化的内部类而外部类不是。但是,在我的情况下,当内部类是时,我不需要实例化外部类。内在根本不需要外在。它的结构只有这样,以便外部类可以访问内部的成员。

这就是我课程的备忘录描述中所说的:

... 这也是有道理的。只有模型应该能够访问 Memento 中的详细信息。 “看守人”对象(处理将数据保存到磁盘/从磁盘检索数据的对象)不应在对象内部看到。由于 Java 没有友元类,这应该是要走的路。

这是否意味着为了按照建议实现它,我不能使用序列化?

编辑:

我将 Memento 类和 Stats 类设为静态,但仍然出现错误。 Model.Stats中似乎还有this的引用

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)

【问题讨论】:

  • 您的类 Model 或其内部类 Stats 具有包含对不可序列化对象的引用的成员或(匿名)内部类。

标签: java serialization memento


【解决方案1】:

非静态内部类的实例具有对其外部类实例的隐藏引用。这意味着如果您要序列化内部类的实例,外部类的实例将与它一起序列化。如果外部类不可序列化,您将获得java.io.NotSerializableException

如果不希望外部类的实例与内部类的实例一起被序列化,则将内部类设为static:

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

static 内部类没有对其外部类实例的引用。

【讨论】:

  • (..因为我正在写评论..)静态术语让我感到困惑,直到现在我才真正查找“嵌套静态类”的含义。事实证明,从“静态成员”、“静态方法”甚至类似 C# 的静态类的意义上说,它不是静态的。不过,我仍然收到 NotSerializableException。请查看已编辑的问题。
  • 可序列化是“传染性的”。 Memento 的所有成员变量的类型也必须是可序列化的。例如,ModelData 也必须是可序列化的,ModelData 所指的所有类型也必须是可序列化的,等等。
  • 通常最好不要使用 Java 序列化,而是使用不同的机制来存储对象状态,最好基于众所周知的标准格式,例如 JSON 或 XML。 Java 序列化使用一种难以理解的二进制格式,并且与源代码的绑定非常紧密(添加一个成员变量,您就无法再读取旧的序列化对象了)。
  • 我想我最终会这样做,它更适合手动调试。不过,我正试图抓住这一点。 Stats 类(以前称为 ModelData)的任何成员都不应该有任何问题 - 它们只是原始类型。
  • Stats 类是什么样的?它有匿名内部类吗?
猜你喜欢
  • 1970-01-01
  • 2014-10-24
  • 2016-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
相关资源
最近更新 更多