Module java.desktop
Package java.beans

Class PersistenceDelegate

java.lang.Object
java.beans.PersistenceDelegate
直接已知的子类:
DefaultPersistenceDelegate

public abstract class PersistenceDelegate extends Object
PersistenceDelegate类负责根据类的公共API中的方法来表达给定类的实例的状态。与将持久性的责任与类本身关联(例如,由ObjectOutputStream使用的readObject和writeObject方法所做的方式)不同,使用此委托模型的流(如XMLEncoder)可以独立于类本身控制其行为。通常,将此信息放在类中是最佳选择,并且可以很容易地在此委托方案中表达约定以实现此目的。然而,有时候,一个类中的小问题可能会阻止整个对象图被写入,这可能会使应用程序开发人员别无选择,只能尝试在本地遮蔽有问题的类或使用替代的持久性技术。在这种情况下,委托模型为应用程序开发人员介入序列化过程的所有部分提供了一个相对清晰的机制,而无需修改不属于应用程序本身的类的实现。

除了使用委托模型外,此持久性方案与传统的序列化方案不同,它要求具有writeObject方法的类似物,而没有相应的readObject方法。writeObject类似物根据其公共API对每个实例进行编码,而无需定义readObject类似物,因为读取序列化形式的过程由Java语言规范中规定的方法调用语义定义。打破writeObject和readObject实现之间的依赖关系(这些实现可能会随版本而更改)是使此技术生成的存档免受它们引用的类的私有实现更改影响的关键因素。

持久性委托可以控制对象持久性的所有方面,包括:

  • 决定是否可以将一个实例变异为同一类的另一个实例。
  • 通过调用公共构造函数或公共工厂方法来实例化对象。
  • 执行对象的初始化。
自版本:
1.4
参见:
  • Constructor Details

    • PersistenceDelegate

      protected PersistenceDelegate()
      构造一个PersistenceDelegate。
  • Method Details

    • writeObject

      public void writeObject(Object oldInstance, Encoder out)
      writeObject是持久性的单一入口点,由Encoder在传统的委托模式下使用。尽管此方法不是final的,但在正常情况下不应需要对其进行子类化。

      此实现首先检查流是否已经遇到此对象。接下来调用mutatesTo方法以查看流返回的候选对象是否可以变异为oldInstance的准确副本。如果可以,将调用initialize方法执行初始化。如果不行,则将候选对象从流中移除,并调用instantiate方法创建此对象的新候选对象。

      参数:
      oldInstance - 将由此表达式创建的实例。
      out - 将写入此表达式的流。
      抛出:
      NullPointerException - 如果out为null
    • mutatesTo

      protected boolean mutatesTo(Object oldInstance, Object newInstance)
      如果可以通过对newInstance应用一系列语句来创建oldInstance的等效副本,则返回true。在此方法的规范中,我们所说的等效是指修改后的实例在其公共API中相关方法的行为上与oldInstance无法区分。[注意:这里我们使用“相关”方法这个短语,而不是“所有”方法,仅因为严格来说,像hashCode和toString这样的方法阻止大多数类生成其实例的真正无法区分的副本]。

      默认行为是如果两个实例的类相同,则返回true。

      参数:
      oldInstance - 要复制的实例。
      newInstance - 要修改的实例。
      返回:
      如果可以通过对oldInstance应用一系列变异来创建newInstance的等效副本,则返回true。
    • instantiate

      protected abstract Expression instantiate(Object oldInstance, Encoder out)
      返回一个值为oldInstance的表达式。此方法用于描述应用于创建给定对象的构造函数或工厂方法。例如,Field类的持久性委托的instantiate方法可以定义如下:
       Field f = (Field)oldInstance;
       return new Expression(f, f.getDeclaringClass(), "getField", new Object[]{f.getName()});
       
      请注意,我们声明返回表达式的值,以便表达式的值(由getValue返回)与oldInstance完全相同。
      参数:
      oldInstance - 将由此表达式创建的实例。
      out - 将写入此表达式的流。
      返回:
      一个值为oldInstance的表达式。
      抛出:
      NullPointerException - 如果out为null并且此值在方法中使用
    • initialize

      protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out)
      生成一系列对newInstance具有副作用的语句,以使新实例变得等效于oldInstance。在此方法的规范中,我们所说的等效是指,方法返回后,修改后的实例在其公共API中所有方法的行为上与newInstance无法区分。

      通常,此实现通过生成涉及oldInstance及其公开可用状态的一系列“发生了什么”语句来实现此目标。这些语句通过其writeExpression方法发送到输出流,该方法返回涉及克隆环境中元素的表达式,模拟读取期间输入流的状态。返回的每个语句将已将旧环境中的所有实例替换为新环境中存在的对象。特别是,对这些语句目标的引用,起初是对oldInstance的引用,将作为对newInstance的引用返回。执行这些语句会将两个对象的状态作为对新环境中对象的一系列修改的增量对齐。到initialize方法返回时,通过使用它们的公共API,应该无法通过区分两个实例来告诉它们。最重要的是,用于使这些对象看起来等效的步骤序列将被记录在输出流中,并在刷新流时形成实际输出。

      默认实现调用类型的超类的initialize方法。

      参数:
      type - 实例的类型
      oldInstance - 要复制的实例。
      newInstance - 要修改的实例。
      out - 应将任何初始化语句写入的流。
      抛出:
      NullPointerException - 如果out为null