我试图理解为什么java.util.Properties以这种方式实现。它有两个接口:getProperty / setProperty只接受字符串,put / get接受任何对象作为值。这两个接口看起来是重叠的,因此可以使用getProperty()检索添加了put()的字符串。
这种奇怪的混合接口似乎存在一些问题。放置一个覆盖字符串属性的对象具有清除字符串值的副作用,产生null作为getProperty结果。添加整数或其他具有简单字符串转换的值可能会被误解为属性值(但作为属性,它总是为空)。
我的问题是:这有真正的,实际的原因吗?或者,我怀疑这是一个半生不熟的实施?
答案 0 :(得分:14)
[来自第4章]在
Properties
的情况下,设计者希望只允许字符串作为键和值,但直接访问基础Hashtable
允许这个不变量被违反了。违反此不变量后,将无法再使用Properties API的其他部分(load
和store
)。当发现这个问题时,纠正它为时已晚,因为客户端依赖于使用非字符串键和值。
该文本是在使用组合而不是继承的上下文中。他基本上使用它作为何时应该使用组合而不是继承的示例。如果Properties
包裹Map
而不是扩展一个,则可以强制使用String
作为键和值的不变。
所以答案是:这是一种疏忽。
答案 1 :(得分:6)
对put
和get
的访问是Properties
是Hashtable
的扩展的结果,不应使用这两种方法(但不能从实现中隐藏由于他们在超类中的公共访问权限。)
Javadocs有一个很好的说明为什么你不应该使用这些方法,而应该只使用字符串:
由于
Properties
继承自Hashtable
,因此put
和putAll
方法可应用于Properties
对象。强烈建议不要使用它们,因为它们允许调用者插入其键或值不是Strings
的条目。应该使用setProperty
方法。如果在包含非store
键或值的“受损”save
对象上调用Properties
或String
方法,则调用将失败。同样,如果在包含非propertyNames
密钥的“受损”list
对象上调用,则对Properties
或String
方法的调用将失败。
正如@yshavit指出的那样,Properties
扩展Hashtable<String, String>
比使用两个对象的散列表更有意义,但这可能是为了保持向后兼容性而做出的决定,因为任何程序都使用任何非String对象的get
/ put
都会被这样的更改破坏。
答案 2 :(得分:2)
官方文件说
因为Properties继承自Hashtable,所以put和putAll方法可以应用于Properties对象。强烈建议不要使用它们,因为它们允许调用者插入其键或值不是字符串的条目。应该使用setProperty方法。如果在包含非String键或值的“受损”Properties对象上调用store或save方法,则调用将失败。同样,如果在包含非String键的“受损”Properties对象上调用propertyNames或list方法,则调用将失败。
http://docs.oracle.com/javase/8/docs/api/java/util/Properties.html
答案 3 :(得分:1)
因为Properties继承自Hashtable,put和putAll方法 可以应用于Properties对象。它们的用途很强烈 不鼓励,因为他们允许调用者插入其键或键的条目 值不是字符串。应该使用setProperty方法。 如果在“受损”属性上调用存储或保存方法 包含非String键或值的对象,调用将失败。 同样,如果调用propertyNames或list方法将失败 它在包含a的“受损”属性对象上调用 非字符串键。
答案 4 :(得分:0)
Properties
扩展了Hashtable
,因此您可以在任何可以使用Properties
的地方使用Hashtable
。
Hashtable
类是get()
和put()
函数的来源。
答案 5 :(得分:0)
put(key, value)
和get(key)
是在当天Properties
延长Hashtable
的可疑决定的遗留问题。这种行为不会发生变化,因为它会破坏向后兼容性,但任何一半体面的样式指南,包括API文档本身,都会建议永远不要使用这些方法。
答案 6 :(得分:0)
正如其他人所说的那样,你只能将它用于Strings。有一些方法可以将对象序列化为字符串并检索它,但显然它并不意味着它。我知道它真的很烦人,因为它是最接近保存和检索应用数据的跨平台方式。据我所知,尽管大多数操作系统都有appdata目录,但在用户隐藏的文件夹中除了字符串之外没有其他正式方法可以保存。