Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Putting objects into java.util.Properties

Tags:

java

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().

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).

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

like image 202
James Watkins Avatar asked May 21 '15 18:05

James Watkins


2 Answers

Joshua Bloch mentions this explicitly in Effective 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.

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.

like image 52
MadConan Avatar answered Oct 27 '22 14:10

MadConan


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).

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

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.

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.

like image 40
FThompson Avatar answered Oct 27 '22 15:10

FThompson