将对象放入java.util.Properties

时间:2021-08-09 19:38:35

I'm trying to understand why java.util.Properties was implemented in this way. It has two interfaces: getProperty/setProperty which only accepts strings, and put/get which accepts any object as a value. These two interfaces appear to be overlapping, so a string added with put() can be retrieved using getProperty().

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

There seems to be some problems with this weird hybrid interface. Putting an object that overrides a string property has the side-effect of clearing the string value, producing null as the getProperty result. Adding an integer, or some other value that has a simple string translation, might be misunderstood as being a real property value (but as a property it's always null).

这个奇怪的混合界面似乎有一些问题。放置一个重写字符串属性的对象,会产生清除字符串值的副作用,产生getProperty结果为null。添加一个整数或其他具有简单字符串转换的值,可能会被误解为一个真正的属性值(但作为属性,它总是null)。

My question is: Is there a real, practical reason for this? Or is it a half-baked implementation as I suspect?

我的问题是:这真的有实际的原因吗?还是像我猜想的那样,它是一个半成品的实现?

7 个解决方案

#1


11  

Joshua Bloch mentions this explicitly in Effective Java

Joshua Bloch在高效Java中明确提到了这一点

[from Chapter 4] In the case of Properties, the designers intended that only strings be allowed as keys and values, but direct access to the underlying Hashtable allows this invariant to be violated. Once this invariant is violated, it is no longer possible to use other parts of the Properties API (load and store). By the time this problem was discovered, it was too late to correct it because clients depended on the use of nonstring keys and values.

[从第4章]在属性的情况下,设计人员希望只允许字符串作为键和值,但是直接访问底层Hashtable允许违背这个不变量。一旦违反了这个不变量,就不再可能使用属性API(加载和存储)的其他部分。当这个问题被发现时,已经太晚了,因为客户端依赖于非字符串键和值的使用。

That text is in context of using composition over inheritance. He's basically using this as an example of when composition should be used instead of inheritance. If Properties wrapped a Map instead of extending one, it could have enforced the invarient of using String as keys and values.

该文本是在使用复合而不是继承的上下文中。他基本上是用这个例子来说明什么时候应该使用组合而不是继承。如果属性包装了映射而不是扩展了映射,那么它可以强制使用字符串作为键和值的不变性。

So the answer is: It was an oversight.

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

#2


5  

Access to put and get is a result of Properties being an extension of Hashtable, and the two method should not be used (but cannot be hidden from implementation due to their public access in the superclass).

对put和get的访问是由于属性是Hashtable的扩展,所以不应该使用这两个方法(但是由于它们在超类中的公共访问,所以不能对实现进行隐藏)。

The Javadocs have a nice note about why you shouldn't use those methods, and should instead only use strings:

Javadocs很好地说明了为什么不应该使用这些方法,而应该只使用字符串:

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead. If the store or save method is called on a "compromised" Properties object that contains a non-String key or value, the call will fail. Similarly, the call to the propertyNames or list method will fail if it is called on a "compromised" Properties object that contains a non-String key.

因为属性继承自Hashtable,所以put和putAll方法可以应用于属性对象。强烈建议不要使用它们,因为它们允许调用者插入键或值不是字符串的条目。应该使用setProperty方法。如果在包含非字符串键或值的“折衷”属性对象上调用store或save方法,则调用将失败。类似地,对propertyNames或list方法的调用在包含非字符串键的“折衷”属性对象上调用时将失败。

As @yshavit notes, it'd make more sense for Properties to extend Hashtable<String, String> than a hashtable of two objects, but this was likely a decision made to maintain backwards compatibility, as any programs using get/put with any non-String objects would have been broken by such a change.

正如@yshavit指出的,属性扩展Hashtable 要比扩展两个对象的Hashtable更有意义,但这很可能是为了保持向后兼容性,因为使用get/put的任何非字符串对象的程序都可能会因为这样的更改而被破坏。 ,>

#3


2  

Official documentations says

官方的文件说

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead. If the store or save method is called on a "compromised" Properties object that contains a non-String key or value, the call will fail. Similarly, the call to the propertyNames or list method will fail if it is called on a "compromised" Properties object that contains a non-String key.

因为属性继承自Hashtable,所以put和putAll方法可以应用于属性对象。强烈建议不要使用它们,因为它们允许调用者插入键或值不是字符串的条目。应该使用setProperty方法。如果在包含非字符串键或值的“折衷”属性对象上调用store或save方法,则调用将失败。类似地,对propertyNames或list方法的调用在包含非字符串键的“折衷”属性对象上调用时将失败。

http://docs.oracle.com/javase/8/docs/api/java/util/Properties.html

http://docs.oracle.com/javase/8/docs/api/java/util/Properties.html

#4


0  

From the Java Docs

从Java文档

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead. If the store or save method is called on a "compromised" Properties object that contains a non-String key or value, the call will fail. Similarly, the call to the propertyNames or list method will fail if it is called on a "compromised" Properties object that contains a non-String key.

因为属性继承自Hashtable,所以put和putAll方法可以应用于属性对象。强烈建议不要使用它们,因为它们允许调用者插入键或值不是字符串的条目。应该使用setProperty方法。如果在包含非字符串键或值的“折衷”属性对象上调用store或save方法,则调用将失败。类似地,对propertyNames或list方法的调用在包含非字符串键的“折衷”属性对象上调用时将失败。

#5


0  

Properties extends Hashtable, so you can use Properties anywhere you can use a Hashtable.

属性扩展了Hashtable,因此您可以在任何可以使用散列表的地方使用属性。

The Hashtable class is where the get() and put() functions are coming from.

Hashtable类是get()和put()函数的来源。

#6


0  

put(key, value) and get(key) are remainders of a questionable decision to have Properties extend Hashtable back in the day. This behavior can't be changes since it will break backwards compatibility, but any half decent style guide, including the API documentation itself, will recommend to never use these methods.

put(key, value)和get(key)是让属性扩展Hashtable回到过去的问题。这种行为不能改变,因为它会破坏向后兼容性,但是任何半好的样式指南,包括API文档本身,都会建议永远不要使用这些方法。

#7


0  

As others have said, you're only supposed to use it for Strings. There are ways of serializing an object as a string and retrieving it, but obviously it's not meant for that. I understand that it's really annoying since its the closest you can get to a cross-platform way of saving and retrieving app data. As far as I know there's no official way to save things other than strings in a folder that is hidden from the user, despite the fact that most operating systems have appdata directories.

就像其他人说的,你应该只在字符串中使用它。有将对象序列化为字符串并检索它的方法,但是很明显,这并不是它的本意。我知道这很烦人,因为这是最接近于跨平台保存和检索应用数据的方式。据我所知,除了将字符串保存在对用户隐藏的文件夹中之外,没有其他的官方方法,尽管大多数操作系统都有appdata目录。

#1


11  

Joshua Bloch mentions this explicitly in Effective Java

Joshua Bloch在高效Java中明确提到了这一点

[from Chapter 4] In the case of Properties, the designers intended that only strings be allowed as keys and values, but direct access to the underlying Hashtable allows this invariant to be violated. Once this invariant is violated, it is no longer possible to use other parts of the Properties API (load and store). By the time this problem was discovered, it was too late to correct it because clients depended on the use of nonstring keys and values.

[从第4章]在属性的情况下,设计人员希望只允许字符串作为键和值,但是直接访问底层Hashtable允许违背这个不变量。一旦违反了这个不变量,就不再可能使用属性API(加载和存储)的其他部分。当这个问题被发现时,已经太晚了,因为客户端依赖于非字符串键和值的使用。

That text is in context of using composition over inheritance. He's basically using this as an example of when composition should be used instead of inheritance. If Properties wrapped a Map instead of extending one, it could have enforced the invarient of using String as keys and values.

该文本是在使用复合而不是继承的上下文中。他基本上是用这个例子来说明什么时候应该使用组合而不是继承。如果属性包装了映射而不是扩展了映射,那么它可以强制使用字符串作为键和值的不变性。

So the answer is: It was an oversight.

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

#2


5  

Access to put and get is a result of Properties being an extension of Hashtable, and the two method should not be used (but cannot be hidden from implementation due to their public access in the superclass).

对put和get的访问是由于属性是Hashtable的扩展,所以不应该使用这两个方法(但是由于它们在超类中的公共访问,所以不能对实现进行隐藏)。

The Javadocs have a nice note about why you shouldn't use those methods, and should instead only use strings:

Javadocs很好地说明了为什么不应该使用这些方法,而应该只使用字符串:

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead. If the store or save method is called on a "compromised" Properties object that contains a non-String key or value, the call will fail. Similarly, the call to the propertyNames or list method will fail if it is called on a "compromised" Properties object that contains a non-String key.

因为属性继承自Hashtable,所以put和putAll方法可以应用于属性对象。强烈建议不要使用它们,因为它们允许调用者插入键或值不是字符串的条目。应该使用setProperty方法。如果在包含非字符串键或值的“折衷”属性对象上调用store或save方法,则调用将失败。类似地,对propertyNames或list方法的调用在包含非字符串键的“折衷”属性对象上调用时将失败。

As @yshavit notes, it'd make more sense for Properties to extend Hashtable<String, String> than a hashtable of two objects, but this was likely a decision made to maintain backwards compatibility, as any programs using get/put with any non-String objects would have been broken by such a change.

正如@yshavit指出的,属性扩展Hashtable 要比扩展两个对象的Hashtable更有意义,但这很可能是为了保持向后兼容性,因为使用get/put的任何非字符串对象的程序都可能会因为这样的更改而被破坏。 ,>

#3


2  

Official documentations says

官方的文件说

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead. If the store or save method is called on a "compromised" Properties object that contains a non-String key or value, the call will fail. Similarly, the call to the propertyNames or list method will fail if it is called on a "compromised" Properties object that contains a non-String key.

因为属性继承自Hashtable,所以put和putAll方法可以应用于属性对象。强烈建议不要使用它们,因为它们允许调用者插入键或值不是字符串的条目。应该使用setProperty方法。如果在包含非字符串键或值的“折衷”属性对象上调用store或save方法,则调用将失败。类似地,对propertyNames或list方法的调用在包含非字符串键的“折衷”属性对象上调用时将失败。

http://docs.oracle.com/javase/8/docs/api/java/util/Properties.html

http://docs.oracle.com/javase/8/docs/api/java/util/Properties.html

#4


0  

From the Java Docs

从Java文档

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead. If the store or save method is called on a "compromised" Properties object that contains a non-String key or value, the call will fail. Similarly, the call to the propertyNames or list method will fail if it is called on a "compromised" Properties object that contains a non-String key.

因为属性继承自Hashtable,所以put和putAll方法可以应用于属性对象。强烈建议不要使用它们,因为它们允许调用者插入键或值不是字符串的条目。应该使用setProperty方法。如果在包含非字符串键或值的“折衷”属性对象上调用store或save方法,则调用将失败。类似地,对propertyNames或list方法的调用在包含非字符串键的“折衷”属性对象上调用时将失败。

#5


0  

Properties extends Hashtable, so you can use Properties anywhere you can use a Hashtable.

属性扩展了Hashtable,因此您可以在任何可以使用散列表的地方使用属性。

The Hashtable class is where the get() and put() functions are coming from.

Hashtable类是get()和put()函数的来源。

#6


0  

put(key, value) and get(key) are remainders of a questionable decision to have Properties extend Hashtable back in the day. This behavior can't be changes since it will break backwards compatibility, but any half decent style guide, including the API documentation itself, will recommend to never use these methods.

put(key, value)和get(key)是让属性扩展Hashtable回到过去的问题。这种行为不能改变,因为它会破坏向后兼容性,但是任何半好的样式指南,包括API文档本身,都会建议永远不要使用这些方法。

#7


0  

As others have said, you're only supposed to use it for Strings. There are ways of serializing an object as a string and retrieving it, but obviously it's not meant for that. I understand that it's really annoying since its the closest you can get to a cross-platform way of saving and retrieving app data. As far as I know there's no official way to save things other than strings in a folder that is hidden from the user, despite the fact that most operating systems have appdata directories.

就像其他人说的,你应该只在字符串中使用它。有将对象序列化为字符串并检索它的方法,但是很明显,这并不是它的本意。我知道这很烦人,因为这是最接近于跨平台保存和检索应用数据的方式。据我所知,除了将字符串保存在对用户隐藏的文件夹中之外,没有其他的官方方法,尽管大多数操作系统都有appdata目录。