Nope, it's still a Hashtable<?,?>, i.e. a Hashtable<Object,Object>. Where is all this going? Well I had a class that had a Properties object as a member variable. I had a method that needed to return all the property names of that Properties object. I thought it would make sense for my method to return a Collection<String>. Since Properties extends Hashtable, I could just return it's keySet() method. This is a Set of all the keys in the Hashtable backing the Properties, thus it is a Set of Strings (Set<String>) and thus a Collection<String>. Too easy.
Wrong again. The return type of the keySet() method is a Set<object>, because Properties extends Hashtable<Object,Object>. You cannot case a Set<Object> to a Set<String>. I was very surprised by this. I expected to have throw a @SuppressWarning("unchecked") annotation on my method, but I did not expect that it would be a compilation error. I figure this is because I would be casting a generic interface. I guess. I could do something completely ridiculous:
return (HashSet<String>)new HashSet(myProps.keySet());
This worked with a good 'ol @SuppressWarning("unchecked") annotation. I had to copy my keySet() into a concrete Set object, and then I could cast. Totally ridiculous.
This all came because my Properties object was being injected with Spring. In other words I had a Spring context file with something like:
<property name="myProps">
<props>
<prop key="a">1</prop>
...
I simply replaced this with a map:
<property name="myProps">
<map>
<entry key="a" value="1">
....
I could then make myProps into a Map<String,String> instead of a Properties object, and simply return it's keySet() without any casting. Very nice. So this just brings me back to the original question of why doesn't Properties extend Hashtable<String,String>?
3 comments:
this is one of the least explicable Java library warts I've ever come across
I'd love to know if there is a justifiable reason...
The only reason I can conceive of is to avoid breaking old code that made (improper) use of the fact that Properties was backed with a Map<Object, Object>.
The real mystery is why did they create Properties by _inheriting_ from a Map instead of just containing one? Composition allows for all the type-safety one could ask for.
Oh well. At this point probably the best we can hope for is that Properties will be deprecated and a new class, done better, will be introduced.
Use stringPropertyNames() with Java 6. See also http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6253413
Post a Comment