Module  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 应该抛出异常:如果调用者对底层操作系统没有足够的权限来执行请求的操作。 例如,如果非特权用户尝试修改系统首选项,这将在大多数系统上发生。 (所需的权限将从实现到实现有所不同,在某些实现中,它们是修改文件系统中某些目录的内容的权利;在其他实现中,它们是修改注册表中某些密钥的内容的权利。)在任何在这种情况下,通常不宜让程序继续执行,就好像这些操作将在以后永久存在一样。 虽然在这种情况下实现不需要抛出异常,但是鼓励它们这样做。 A 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)

        这个实现首先检查是否keynull抛出一个NullPointerException如果是这种情况。 然后它获取此首选项节点的锁定,检查节点是否尚未被删除,调用getSpi(String) ,并返回结果,除非getSpi调用返回null或引发异常,在这种情况下,此调用将返回def

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

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

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

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

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

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

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

        Specified by:
        parentPreferences
        结果
        此首选项节点的父级。
        异常
        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并且有任何节点更改侦听器, true通知事件排入队列,以便事件分派线程进行处理。

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

        如果path的第一个字符为'/' (表示绝对路径名称),则在将path分解为令牌之前,将首选节点的锁定被删除,并且此方法递归地遍历从根开始的路径(而不是从该节点开始)。 遍历与所描述的相对路径名称相同。 根据locking invariant ,在根节点开始遍历之前删除此节点上的锁是至关重要的,以避免死锁的可能性。

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

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

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

        请注意,所有祖先始终调用助手方法,直到“最近的未删除祖先”被锁定。

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

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

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

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

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

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

        Specified by:
        absolutePathPreferences
        结果
        这个偏好节点的绝对路径名。
      • isUserNode

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

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

        Specified by:
        isUserNodePreferences
        结果
        true如果此首选项节点在用户首选项树中, false如果它在系统首选项树中。
      • addPreferenceChangeListener

        public void addPreferenceChangeListener​(PreferenceChangeListener pcl)
        说明从类别复制: Preferences
        注册指定的侦听器以接收此首选项节点的优先级更改事件 当偏好被添加到该节点,从该节点移除时,或者当与偏好相关联的值被改变时,生成偏好改变事件。 (偏好改变事件不会由所产生的Preferences.removeNode()方法,该方法生成事件 。优选变化事件由所生成的节点改变 clear方法)。

        事件只能保证在与注册的侦听器相同的JVM中进行的更改,尽管某些实现可能会为此JVM之外的更改生成事件。 可能在更改持续存在之前生成事件。 当在该节点的后代修改首选项时,不会生成事件; 想要这样的事件的主叫必须向每个后代注册。

        Specified by:
        addPreferenceChangeListenerPreferences
        参数
        pcl - 要添加的首选项更改侦听器。
        另请参见:
        Preferences.removePreferenceChangeListener(PreferenceChangeListener)Preferences.addNodeChangeListener(NodeChangeListener)
      • addNodeChangeListener

        public void addNodeChangeListener​(NodeChangeListener ncl)
        描述从类复制: Preferences
        注册指定的侦听器以接收该节点的节点更改事件 当子节点添加到该节点或从该节点移除时,将生成节点更改事件。 (单个Preferences.removeNode()调用导致多个节点更改事件 ,一个针对根除在已删除节点的子树中的每个节点)。

        事件只能保证在与注册的侦听器相同的JVM中进行的更改,尽管某些实现可能会为此JVM之外的更改生成事件。 在更改变得永久之前可能会生成事件。 当添加或删除此节点的间接后代时,不会生成事件; 想要这样的事件的主叫必须向每个后代注册。

        关于节点创建几乎不能保证。 因为在访问时隐式创建节点,因此实现可能无法确定在访问之前后备存储中是否存在子节点(例如,因为后备存储不可达或缓存的信息已过期)。 在这种情况下,实现既不需要生成节点更改事件,也不禁止这样做。

        Specified by:
        addNodeChangeListenerPreferences
        参数
        ncl - 要添加的 NodeChangeListener
        另请参见:
        Preferences.removeNodeChangeListener(NodeChangeListener)Preferences.addPreferenceChangeListener(PreferenceChangeListener)
      • 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:
        toStringPreferences
        结果
        对象的字符串表示形式。
      • sync

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

        此实现调用一个递归的帮助程序来锁定此节点,调用它上的syncSpi(),解锁该节点,并递归地调用每个“缓存的子”的方法。 缓存的子节点是此虚拟机中已创建但未随后删除的此节点的子节点。 实际上,该方法对根据此节点的“高速缓存子树”进行深度优先遍历,仅在该节点被锁定时调用子树中每个节点上的syncSpi()。 请注意,syncSpi()是从上而下调用的。

        Specified by:
        syncPreferences
        异常
        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(),解锁此节点,并递归地在每个“缓存的子节点”上调用此方法。 缓存的子节点是此虚拟机中已创建但未随后删除的此节点的子节点。 实际上,此方法会深入第一遍遍历此节点的“缓存子树”,在子树中的每个节点上调用flushSpi(),而只锁定该节点。 请注意,flushSpi()是从上而下调用的。

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

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

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

        如果此节点抛出一个BackingStoreException ,异常将传播超出封闭的flush()调用。

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

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