模块  java.prefs
软件包  java.util.prefs

Class AbstractPreferences


  • public abstract class AbstractPreferences
    extends Preferences
    该类提供了Preferences类的骨干实现,极大地简化了实现它的任务。

    本课程仅适用于Preferences实施者。 Preferences设施的普通用户无需查阅此文档。 Preferences文档应该足够了。

    实现者必须重写九个抽象服务提供者接口(SPI)方法: getSpi(String)putSpi(String,String)removeSpi(String)childSpi(String)removeNodeSpi()keysSpi()childrenNamesSpi()syncSpi()flushSpi() 所有具体方法都精确地指定了它们如何在这些SPI方法上实现。 如果默认实现因任何原因(例如性能)不能令人满意,则实现者可以自行决定覆盖一个或多个具体方法。

    SPI方法分为三组,涉及异常行为。 getSpi方法永远不应该抛出异常,但它并不重要,因为此方法抛出的任何异常都将被get(String,String)截获,它将返回指定的默认值给调用者。 指定removeNodeSpi, keysSpi, childrenNamesSpi, syncSpiflushSpi方法抛出BackingStoreException ,如果无法执行操作,则需要执行此检查异常。 异常向外传播,导致相应的API方法失败。

    其余的SPI方法putSpi(String,String)removeSpi(String)childSpi(String)有更复杂的异常行为。 它们未被指定投掷BackingStoreException ,因为即使后备存储不可用,它们通常也可以遵守它们的合同。 这是真的,因为它们不会返回任何信息,并且在随后调用Preferences.flush()Preferences.sync()之前,它们的效果不需要成为永久性的。 一般来说,这些SPI方法不应抛出异常。 在一些实现中,可能存在这样的情况,在这些情况下,这些调用甚至不能将所请求的操作排队以供稍后处理。 即使在这些情况下,通常最好简单地忽略调用和返回,而不是抛出异常。 但是,在这种情况下,随后援引flush()sync并不意味着所有先前的行动都已成功永久化。

    putSpi, removeSpi and childSpi 应该抛出异常的一种情况是:如果调用者在底层操作系统上缺少足够的权限来执行请求的操作。 例如,如果非特权用户尝试修改系统首选项,则会在大多数系统上发生这种情况。 (所需的权限因实现而异。在某些实现中,它们是修改文件系统中某些目录内容的权利;在其他实现中,它们是修改注册表中某些键的内容的权利。)在这些情况下,通常不希望程序继续执行,好像这些操作将在以后成为永久性的。 虽然在这些情况下不需要实现抛出异常,但鼓励它们这样做。 SecurityException是合适的。

    大多数SPI方法都需要实现在首选项节点读取或写入信息。 实现者应该注意另一个VM可能同时从后备存储中删除了该节点的事实。 如果节点已被删除,则重建节点是实现的责任。

    实施说明:在Sun的默认Preferences实施中,用户的身份从底层操作系统继承,并且在虚拟机的生命周期内不会更改。 应认识到,服务器端Preferences实现可以具有从请求到请求的用户身份变化,通过使用静态ThreadLocal实例隐式地传递给Preferences方法。 强烈建议此类实现的作者在访问首选项时(例如通过get(String,String)put(String,String)方法)确定用户,而不是将用户与每个Preferences实例永久关联。 后一种行为与正常的Preferences使用相冲突,会导致很大的混乱。

    从以下版本开始:
    1.4
    另请参见:
    Preferences
    • 字段详细信息

      • newNode

        protected boolean newNode
        如果在创建此对象之前,后备存储中不存在此节点,则此字段应为true 该字段初始化为false,但可以由子类构造函数设置为true(此后不应对其进行修改)。 此字段指示在创建完成时是否应触发节点更改事件。
      • lock

        protected final Object lock
        一个对象,其监视器用于锁定此节点。 该对象优先于节点本身使用,以减少由于锁定节点而故意或无意拒绝服务的可能性。 为避免死锁,节点永远不会被持有该节点后代锁的线程锁定。
    • 构造方法详细信息

      • AbstractPreferences

        protected AbstractPreferences​(AbstractPreferences parent,
                                      String name)
        创建具有指定父级和相对于其父级的指定名称的首选项节点。
        参数
        parent - 此首选项节点的父节点,如果这是根节点,则为null。
        name - 此首选项节点相对于其父节点的名称,如果这是根节点, ""
        异常
        IllegalArgumentException - 如果 name包含斜杠( '/' ),或 parentnull且名称不是 ""
    • 方法详细信息

      • get

        public String get​(String key,
                          String def)
        实现get方法按照在本说明书中Preferences.get(String,String)

        如果是这种情况,此实现首先检查key是否为null抛出NullPointerException 然后它获取此首选项节点的锁,检查该节点是否已被删除,调用getSpi(String) ,并返回结果,除非getSpi调用返回null或抛出异常,在这种情况下,此调用返回def

        Specified by:
        get在类 Preferences
        参数
        key - 要返回其关联值的键。
        def - 此首选项节点没有与 key关联的值时要返回的值。
        结果
        值相关联的 key ,或 def如果没有值相关联 key
        异常
        IllegalStateException - 如果已使用 removeNode()方法删除此节点(或祖先)。
        NullPointerException - 如果密钥是null (A null默认允许的。)
        IllegalArgumentException - 如果key包含空控制字符,则代码点U + 0000。
      • childrenNames

        public String[] childrenNames()
                               throws BackingStoreException
        实现children方法按照在本说明书中Preferences.childrenNames()

        此实现获取此首选项节点的锁定,检查该节点是否已被删除,构造一个TreeSet初始化为已缓存的子节点的名称(此节点中的子节点为“子缓存”),调用childrenNamesSpi() ,并添加所有返回的子名称进入集合。 使用toArray方法将树集的元素转储到String数组中,并返回此数组。

        Specified by:
        childrenNames ,类 Preferences
        结果
        此首选项节点的子节点的名称。
        异常
        BackingStoreException - 如果由于后备存储中的故障或无法与之通信而无法完成此操作。
        IllegalStateException - 如果已使用 removeNode()方法删除此节点(或祖先)。
        另请参见:
        cachedChildren()
      • cachedChildren

        protected final AbstractPreferences[] cachedChildren()
        返回此节点的所有已知未删除子节点。
        结果
        此节点的所有已知未删除的子节点。
      • parent

        public Preferences parent()
        实现parent方法按照在本说明书中Preferences.parent()

        此实现获取此首选项节点的锁,检查该节点是否已被删除,并返回传递给此节点的构造函数的父值。

        Specified by:
        parent在类 Preferences
        结果
        此首选项节点的父节点。
        异常
        IllegalStateException - 如果已使用 removeNode()方法删除此节点(或祖先)。
      • node

        public Preferences node​(String path)
        实现node方法按照在本说明书中Preferences.node(String)

        此实现获取此首选项节点的锁定并检查该节点是否尚未删除。 如果path"" ,则返回此节点; 如果path"/" ,则返回此节点的根。 如果path的第一个字符不是'/' ,则实现将path分解为标记,并递归遍历从此节点到命名节点的路径,在遍历的每个步骤中“使用” path中的名称和斜杠。 在每个步骤中,锁定当前节点并检查节点的子缓存以查找命名节点。 如果未找到,则检查名称以确保其长度不超过MAX_NAME_LENGTH 然后调用childSpi(String)方法,并将结果存储在此节点的子缓存中。 如果新创建的Preferences对象的newNode字段为true并且存在任何节点更改侦听器,则会将通知事件排入队列以供事件派发线程处理。

        当没有更多令牌时,此方法将返回在子缓存中找到的或由childSpi返回的最后一个值。 如果在遍历期间,两个"/"令牌连续发生,或者最终令牌为"/" (而不是名称),则抛出相应的IllegalArgumentException

        如果path的第一个字符是'/' (表示绝对路径名),则在将path分解为标记之前删除此首选项节点的锁定,并且此方法以递归方式遍历从根开始的路径(而不是从此节点开始)。 遍历在其他方面与针对相对路径名描述的遍历相同。 根据locking invariant ,在开始根节点的遍历之前删除此节点上的锁是必不可少的,以避免死锁的可能性。

        Specified by:
        node在类 Preferences
        参数
        path - 要返回的首选项节点的路径名。
        结果
        指定的首选项节点。
        异常
        IllegalArgumentException - 如果路径名无效(即,它包含多个连续的斜杠字符,或以斜杠字符结尾且长度超过一个字符)。
        IllegalStateException - 如果已使用 removeNode()方法删除此节点(或祖先)。
        另请参见:
        Preferences.flush()
      • removeNode

        public void removeNode()
                        throws BackingStoreException
        实现removeNode()方法按照在本说明书中Preferences.removeNode()

        此实现检查此节点是否为根; 如果是这样,它会抛出一个适当的例外。 然后,它锁定此节点的父节点,并调用遍历以此节点为根的子树的递归助手方法。 递归方法锁定调用它的节点,检查它是否尚未被删除,然后确保缓存它的所有子节点 :调用childrenNamesSpi()方法并检查每个返回的子名称是否包含在子节点中 -缓存。 如果尚未缓存子级,则调用childSpi(String)方法为其创建Preferences实例,并将此实例放入子级缓存中。 然后,helper方法在其子缓存中包含的每个节点上递归调用自身。 接下来,它调用removeNodeSpi() ,将自身标记为已删除,并将其自身从其父级的子缓存中删除。 最后,如果有任何节点更改侦听器,它会将通知事件排入队列以供事件派发线程处理。

        请注意,始终调用辅助方法,所有祖先都锁定到“最近的非移除祖先”。

        Specified by:
        removeNode在类 Preferences
        异常
        IllegalStateException - 如果已使用 removeNode()方法删除此节点(或祖先)。
        UnsupportedOperationException - 如果在根节点上调用此方法。
        BackingStoreException - 如果由于后备存储中的故障或无法与其通信而无法完成此操作。
        另请参见:
        Preferences.flush()
      • name

        public String name()
        实现name方法按照在本说明书中Preferences.name()

        此实现仅返回传递给此节点的构造函数的名称。

        Specified by:
        name在类 Preferences
        结果
        此首选项节点的名称,相对于其父节点。
      • absolutePath

        public String absolutePath()
        实现absolutePath方法按照在本说明书中Preferences.absolutePath()

        此实现仅返回在构造此节点时计算的绝对路径名(基于传递给此节点的构造函数的名称,以及传递给此节点的祖先构造函数的名称)。

        Specified by:
        absolutePath在类 Preferences
        结果
        此首选项节点的绝对路径名称。
      • isUserNode

        public boolean isUserNode()
        实现isUserNode方法按照在本说明书中Preferences.isUserNode()

        此实现将此节点的根节点(存储在私有字段中)与Preferences.userRoot()返回的值进行比较 如果两个对象引用相同,则此方法返回true。

        Specified by:
        isUserNode在类 Preferences
        结果
        true如果此首选项节点位于用户首选项树中, false如果它位于系统首选项树中)。
      • putSpi

        protected abstract void putSpi​(String key,
                                       String value)
        将给定的键值关联放入此首选项节点。 保证keyvalue非空且合法长度。 此外,保证此节点尚未被删除。 (实现者无需检查这些内容。)

        在保持此节点的锁定的情况下调用此方法。

        参数
        key - 关键
        value - 该值
      • getSpi

        protected abstract String getSpi​(String key)
        返回与此首选项节点处的指定键关联的值,如果此键没有关联,则null ,或者此时无法确定关联。 保证key非空。 此外,保证此节点尚未被删除。 (实现者无需检查这些内容。)

        一般来说,这种方法在任何情况下都不应该抛出异常。 但是,如果它确实抛出异常,则异常将被拦截并视为null返回值。

        在保持此节点的锁定的情况下调用此方法。

        参数
        key - 关键
        结果
        与此首选项节点上的指定键关联的值,如果此键没有关联, null ,或者此时无法确定关联。
      • removeSpi

        protected abstract void removeSpi​(String key)
        删除此首选项节点上指定键的关联(如果有)。 保证key非空。 此外,保证此节点尚未被删除。 (实现者无需检查这些内容。)

        在保持此节点的锁定的情况下调用此方法。

        参数
        key - 关键
      • removeNodeSpi

        protected abstract void removeNodeSpi()
                                       throws BackingStoreException
        删除此首选项节点,使其无效以及它包含的任何首选项。 在进行此调用时,命名子将没有后代(即, Preferences.removeNode()方法以自下而上的方式重复调用此方法,在删除节点本身之前删除每个节点的后代)。

        使用此节点及其父节点上的锁(以及由于单次调用而被删除的所有祖先到Preferences.removeNode() )调用此方法

        在此节点(或祖先)上调用flush方法之前,删除节点不需要持久化。

        如果此节点抛出BackingStoreException ,则异常将超出封闭的removeNode()调用。

        异常
        BackingStoreException - 如果由于后备存储中的故障或无法与之通信而无法完成此操作。
      • keysSpi

        protected abstract String[] keysSpi()
                                     throws BackingStoreException
        返回此首选项节点中具有关联值的所有键。 (如果此节点没有首选项,则返回的数组大小为零。)保证此节点尚未删除。

        在保持此节点的锁定的情况下调用此方法。

        如果此节点抛出BackingStoreException ,则异常将超出封闭的keys()调用。

        结果
        在此首选项节点中具有关联值的键的数组。
        异常
        BackingStoreException - 如果由于后备存储中的故障或无法与之通信而无法完成此操作。
      • childrenNamesSpi

        protected abstract String[] childrenNamesSpi()
                                              throws BackingStoreException
        返回此首选项节点的子节点的名称。 (如果此节点没有子节点,则返回的数组大小为零。)此方法不需要返回已缓存的任何节点的名称,但可以不受损害地返回。

        在保持此节点的锁定的情况下调用此方法。

        如果此节点抛出BackingStoreException ,则异常将传播到封闭的childrenNames()调用之外。

        结果
        包含此首选项节点的子项名称的数组。
        异常
        BackingStoreException - 如果由于后备存储中的故障或无法与之通信而无法完成此操作。
      • getChild

        protected AbstractPreferences getChild​(String nodeName)
                                        throws BackingStoreException
        返回指定子项(如果存在),如果不存在,则返回null 保证nodeName非空,非空,不包含斜杠字符('/'),且不超过Preferences.MAX_NAME_LENGTH字符。 此外,保证此节点尚未被删除。 (如果他选择覆盖此方法,则实现者无需检查这些内容。)

        最后,保证在上一次删除之后,此方法的先前调用或childSpi(java.lang.String)未返回指定节点。 换句话说,将始终优先使用缓存值来调用此方法。 (如果实现者选择覆盖此方法,则无需维护自己先前返回的子缓存。)

        此实现获取此首选项节点的锁定,调用childrenNames()以获取此节点的子节点的名称数组,并迭代数组,将每个子节点的名称与指定的节点名称进行比较。 如果子节点具有正确的名称,则调用childSpi(String)方法并返回结果节点。 如果迭代完成但未找到指定的名称,则返回null

        参数
        nodeName - 要搜索的子项的名称。
        结果
        命名子项(如果存在),如果不存在,则返回null。
        异常
        BackingStoreException - 如果由于后备存储中的故障或无法与之通信而无法完成此操作。
      • childSpi

        protected abstract AbstractPreferences childSpi​(String name)
        返回此首选项节点的指定子节点,如果它尚不存在则创建它。 保证name非空,非空,不包含斜杠字符('/'),且不超过Preferences.MAX_NAME_LENGTH字符。 此外,保证此节点尚未被删除。 (实现者无需检查这些内容。)

        最后,保证在上一次删除之后,此方法的先前调用或getChild(String)尚未返回指定节点。 换句话说,将始终优先使用缓存值来调用此方法。 子类不需要维护自己先前返回的子缓存。

        实现者必须确保尚未删除返回的节点。 如果先前删除了此节点的同名子节点,则实现者必须返回新构造的AbstractPreferences节点; 一旦删除, AbstractPreferences节点就无法“复苏”。

        如果此方法导致创建节点,则在此节点或其祖先(或后代)之一上调用flush方法之前,不保证此节点是持久的。

        在保持此节点的锁定的情况下调用此方法。

        参数
        name - 要相对于此首选项节点返回的子节点的名称。
        结果
        命名子节点。
      • toString

        public String toString()
        返回此首选项节点的绝对路径名。
        Specified by:
        toString在类 Preferences
        结果
        对象的字符串表示形式。
      • sync

        public void sync()
                  throws BackingStoreException
        实现sync方法按照在本说明书中Preferences.sync()

        此实现调用一个递归帮助器方法,该方法锁定此节点,在其上调用syncSpi(),解锁此节点,并在每个“缓存的子节点”上递归调用此方法。 缓存的子级是此VM中已创建的节点的子级,后来不会被删除。 实际上,此方法首先遍历以此节点为根的“缓存子树”,在子树中的每个节点上调用syncSpi(),同时仅锁定该节点。 请注意,自上而下调用syncSpi()。

        Specified by:
        sync ,类 Preferences
        异常
        BackingStoreException - 如果由于后备存储中的故障或无法与之通信而无法完成此操作。
        IllegalStateException - 如果已使用 removeNode()方法删除此节点(或祖先)。
        另请参见:
        flush()
      • syncSpi

        protected abstract void syncSpi()
                                 throws BackingStoreException
        在锁定此节点的情况下调用此方法。 此方法的合同是将存储在此节点的任何缓存首选项与存储在后备存储中的任何缓存首选项同步。 (这是完全可能的,这点上不支持存储存在,可能是因为它已被其他虚拟机删除,或者因为它尚未创建)。注意,在这个任意子节点,此方法不应同步偏好节点。 如果后备存储自然地同时同步整个子树,则鼓励实现者覆盖sync(),而不是仅仅覆盖此方法。

        如果此节点抛出BackingStoreException ,则异常将传播到封闭的sync()调用之外。

        异常
        BackingStoreException - 如果由于后备存储中的故障或无法与之通信而无法完成此操作。
      • flush

        public void flush()
                   throws BackingStoreException
        实现flush方法按照在本说明书中Preferences.flush()

        此实现调用一个递归帮助器方法,该方法锁定此节点,对其调用flushSpi(),解锁此节点,并在每个“缓存的子节点”上递归调用此方法。 缓存的子级是此VM中已创建的节点的子级,后来不会被删除。 实际上,此方法首先遍历以此节点为根的“缓存子树”,在子树中的每个节点上调用flushSpi(),同时仅锁定该节点。 请注意,自上而下调用flushSpi()。

        如果在使用removeNode()方法删除的节点上调用此方法,则在此节点上调用flushSpi(),但在其他节点上不调用flushSpi()。

        Specified by:
        flush ,类 Preferences
        异常
        BackingStoreException - 如果由于后备存储中的故障或无法与之通信而无法完成此操作。
        另请参见:
        flush()
      • flushSpi

        protected abstract void flushSpi()
                                  throws BackingStoreException
        在锁定此节点的情况下调用此方法。 此方法的合同是强制将此首选项节点的内容中的任何缓存更改强制到后备存储,从而保证其持久性。 (这是完全可能的是,该节点上不后备存储器中存在,或者是因为它已被另一个VM删除,或因为它尚未被创建)。注意,在此任何子节点此方法不应冲洗喜好节点。 如果后备存储自然地立即刷新整个子树,则鼓励实现者覆盖flush(),而不是仅仅覆盖此方法。

        如果此节点抛出BackingStoreException ,则异常将传播到封闭的flush()调用之外。

        异常
        BackingStoreException - 如果由于后备存储中的故障或无法与其通信而无法完成此操作。
      • isRemoved

        protected boolean isRemoved()
        返回true如果此节点(或其祖先)已经被除去的removeNode()方法。 此方法在返回用于跟踪此状态的私有字段的内容之前锁定此节点。
        结果
        true iff此节点(或祖先)已使用 removeNode()方法删除。