将对象放入java.util.Properties

Jam*_*ins 12 java

我试图理解为什么java.util.Properties以这种方式实现.它有两个接口:getProperty/setProperty只接受字符串,put/get接受任何对象作为值.这两个接口看起来是重叠的,因此可以使用getProperty()检索添加了put()的字符串.

这个奇怪的混合接口似乎存在一些问题.放置一个覆盖字符串属性的对象具有清除字符串值的副作用,产生null作为getProperty结果.添加整数或其他具有简单字符串转换的值可能会被误解为属性值(但作为属性,它始终为null).

我的问题是:这有一个真实的,实际的原因吗?或者,我怀疑这是一个半生不熟的实施?

Mad*_*nan 16

Joshua BlochEffective Java中明确提到了这一点

[ 来自第4章 ]在这种情况下Properties,设计者希望只允许字符串作为键和值,但直接访问底层Hashtable允许违反此不变量.一旦违反了这个不变量,就不再可能使用Properties API的其他部分(loadstore).当发现这个问题时,纠正它为时已晚,因为客户端依赖于使用非字符串键和值.

该文本是在使用组合而不是继承的上下文中.他基本上使用它作为何时应该使用组合而不是继承的示例.如果Properties包装Map而不是扩展一个,它可以强制使用String作为键和值的不变.

所以答案是:这是一个疏忽.

  • 选择这个答案是因为它解释了为什么以这种方式实现,而不仅仅是"不要使用其他方法".作为旁注,java mail API在设计时使用它来配置自定义SSL套接字工厂.哦,java,我们所拥有的爱恨交织. (2认同)

FTh*_*son 6

访问put并且getProperties作为扩展的结果Hashtable,并且不应该使用这两种方法(但由于它们在超类中的公共访问而不能从实现中隐藏).

Javadoc中有关于为什么你不应该使用这些方法,一个漂亮的音符,而是应该只使用字符串:

因为Properties继承自Hashtable,所以putputAll方法可以应用于Properties对象.强烈建议不要使用它们,因为它们允许调用者插入其键或值不是的条目Strings.setProperty应该使用该方法.如果在包含非键或值的"受损" 对象上调用storeor save方法,则调用将失败.同样,如果在包含非密钥的"受损" 对象上调用,则对or 方法的调用将失败.PropertiesStringpropertyNameslistPropertiesString

正如@yshavit指出的那样,Properties扩展Hashtable<String, String>比两个对象的哈希表更有意义,但这可能是为了保持向后兼容性的决定,因为任何使用get/ put与任何非String对象的程序都会被这样破坏.变化.