参数选择 API | 文档目录 |
所有修改参数数据的方法都允许异步操作。它们可能立即返回并且修改最终会传递给后备存储。 flush方法能用于强制刷新后备存储。
Preferences类中的方法可以在单一JVM下在没有外部同步的情况下通过多线程并发调用。如果这个类被多个使用同一后备存储区存储参数数据的JVM并发调用,数据存储不会被破坏,但是不能保证数据的一致性。
更多细节,可以参看下面的链接:
参数选择API和其它机制的比较 使用的注意事项 设计 FAQ通常,参数和配置数据被存储在配置文件里面,这些文件可以通过java.util.Properties API访问。然而这些文件应该放在何处或者它们应该调用什么没有标准。使用这种机制,备份用户数据或者将它们从一个机器传递到另一个机器将异常的困难。随着应用程序的增加,文件名称冲突可能性就增加。而且,这种机制在没有本机磁盘的平台下是没有用的,或者需要将数据存储在外部的数据存储器上(例如企业范围的 LDAP目录服务)。
在少数情况下,开发者通过JNDI(Java名字和目录接口)API访问目录服务存储用户参数和配置数据。(不像参数API,JNDI允许允许使用任何后备存储(后端中立)。虽然JNDI是异常的强大,但是它也很巨大,它由5个包和83各类组成。JNDI不提供参数数据应该存储在目录名字空间的什么地方的政策。
参数API和JNDI都没有提供一个简单的,普遍地,后端中立的参数管理工具。参数选择API提供了一个这样的工具,它结合了参数选择API的简单和JNDI的后端中立。它在难以达到的后备数据存储方面提供充分的内置政策防止名字冲突、鼓励一致性并且促进健壮性。
参看: 设计 FAQ注意static final 成员而不是它的字面上的字符串用来作为关键字的名字(NUM_ROWS 和 NUM_COLS)。这降低了由于关键字名的印刷上的错误引起的运行时错误的可能性。
同时注意为每个参数提供的合理的缺省值。这些缺省值在参数值没有被设置或者后备存储不可达的情况下被返回。
package com.acme.widget; import java.util.prefs.*; public class Gadget { // Preference keys for this package private static final String NUM_ROWS = "num_rows"; private static final String NUM_COLS = "num_cols"; void foo() { Preferences prefs = Preferences.userNodeForPackage(this); int numRows = prefs.getInt(NUM_ROWS, 40); int numCols = prefs.getInt(NUM_COLS, 80); ... } } 上面的例子为每个用户获取一个参数,如果想获取系统值,foo 中的第一行应该用下面的程序代替: Preferences prefs = Preferences.systemNodeForPackage(this);它有意代替大多数人通常使用的参数API,校正了它的不足同时保持了它的简洁。在使用参数API时,程序员必须明确的指定每个参数文件的路径,但是并没有标准的定位或命名协定。参数文件是“脆弱”的,因为它们可以被手工编辑但是很容易被粗心的编辑破坏。参数文件不能容易的用于除了文件系统外的其他持续机制。总之,参数API工具不合适。
参数选择API如何涉及JNDI?
像JNDI,参数选择API提供后端中立的持久的关键字-值对数据访问。然而JNDI远远要强大,并且相对的庞大。JNDI对于需要它的能力的企业应用合适。参数选择API有意成为简单的,普遍地,后端中立的参数管理工具,使得任何 Java 应用都可以容易的根据用户参数定制它的行为并且从一个进程到另一个进程上维护一个小的状态参数。
为什么所有的get方法都需要调用程序传入一个缺省值?
这强制应用程序作者提供一个合理的缺省值,因而应用程序即使在存储器不可用时也有一个合理的可能值运行。
如何决定什么方法需要抛出一个 BackingStoreException异常?
只有那些在语义上绝对需要和后备存储器通信的方法需要抛出这个异常。通常应用程序不需要调用这些方法。只要这些方法被避免,应用程序即使在后备存储不可用的情况下也可以运行,这是一个清楚地数据目标。
为什么这个API不在多虚拟机并行访问上提供更强的保证? 类似的,为什么这个API允许多个Preferences更新合并为一个单一的“事务”,所有的或者没有语义学上的概念?
虽然这个API提供基本的持续数据存储,但它无意代替数据库。它在标准的参数/配置存储上实现这些是危险的,它的大多数不提供像数据库那样的保证和功能。这样的存储在这个API想要达到的目的上已经被证明是适当的。
为什么这个API是关键字和节点名大小写敏感的,而其他有相同功能的API(例如WIN32注册表和LDAP)不是?
在Java语言里面,大小写敏感的字符串关键字是很普遍的。特别地,它们是由将要被这个API取代的Properties类提供的。以大小写敏感的方式使用Properties对于人们来说是不平常的。例如 Java的包名(也是大小写敏感的)有时也作为关键字。这个设计使得以大小写敏感的关键字在后备存储上实现Preferences的系统程序员的工作变得复杂是公认的,但是这是被考虑过的值得的代价,因为更多的程序员将使用参数选择API而不是实现它。
为什么这个API不使用Java 2的集合结构?
这个API设计用于一个非常精确的目的并为了该目的进行了优化。由于缺乏普通类型(参看
JSR-14), 这个API对于普通用户将不方便。如果强制符合Map API将使得它缺乏编译时的类型安全性。同时也没有期望与其他Map实现互用(尽管如果这个假设是错误的也可以很简单的实现一个适配器类纠正这个假设)。参数选择API的设计和Map是如此相似,以至于熟悉后者的程序员在使用前者上应该没有任何困难。为什么 put 和 remove 方法不返回以前的值?
这两种方法被期望即使是后备存储不可用的情况下也可以执行。如果它们需要返回以前的值,那么这个期望就是不可能的。更进一步的,如果这个API在一些通用的后端数据存储上实现的话将给性能带来负面的影响。
为什么这个API允许但是不要求存储缺省值?
这个功能在企业设置里面是作为标准被要求的,参数选择的成本效益管理贯穿整个企业,但是在自管理的单一用户设置上这个要求就太过分了。
为什么这个API不包含读写可串行化对象的方法?
串行化对象有些脆弱:如果读某个特性的程序的版本和写该特性的程序版本不同,那么对象可能是不完全连续的(或者根本就不连续)。使用这个API存储串行化对象不是不可能的,但是我们不鼓励这样做,并且没有提供一个方便的方法。
为什么Preferences是一个抽象类而不是一个接口?
在向上兼容性上增加新方法的能力的价值超过了Preferences不能作为一个"mixin" (也就是说并不是任何类都可以作为一个Preferences对象进行服务)的缺点。同时,这也避免了个别的类对静态方法的需要。 (接口是不能包含静态方法的。)
<!-- Body text ends here --> <!-- ============================================================== --> Copyright © 2001 Sun Microsystems, Inc. All Rights Reserved. | Java Software |