java.util.Properties extending from HashMap<Object, Object> insteadof HashMap<String, String>

R

Rakesh

I was curious if there is a reason why java.util.Properties extends
from HashMap<Object, Object> instead of HashMap<String, String>
(seems more intuitive to me).

A variation of that would be -
how do we get about converting Properties to Map<String, String> .
 
O

Owen Jacobson

I was curious if there is a reason why java.util.Properties extends
from HashMap<Object, Object> instead of  HashMap<String, String>
(seems more intuitive to me).

A variation of that would be -
   how do we get about converting Properties to Map<String, String> .

Backwards compatability. In Java 1.4 and earlier,
Properties.get(Object) returned Object; changing that signature for
1.5 would break any code that used that method without an immediate
cast to String.

-o
 
R

Rakesh

Backwards compatability. In Java 1.4 and earlier,
Properties.get(Object) returned Object; changing that signature for
1.5 would break any code that used that method without an immediate
cast to String.

-o

Thanks Owen.

From JDK 1.5 onwards - how do I cast Properties to Map<String,
String>

(One obvious answer is to - use the methods - propertyNames() to get
the Enumeration and then use getProperty() to get the property value
and insert it into a new Map).

I was curious if there is any other O(1) way of doing this (like
casting etc.).
 
R

Roedy Green

I was curious if there is a reason why java.util.Properties extends
from HashMap<Object, Object> instead of HashMap<String, String>
(seems more intuitive to me).

Properties predates generics.
 
R

Roedy Green

From JDK 1.5 onwards - how do I cast Properties to Map<String,
String>

(One obvious answer is to - use the methods - propertyNames() to get
the Enumeration and then use getProperty() to get the property value
and insert it into a new Map).

I was curious if there is any other O(1) way of doing this (like
casting etc.).

In general this is a nasty problem in Java. If something is
effectively declared <Object> or Object[] the JVM can't trust you that
all the elements are really something more specific. You have to fish
them out one, lets the cast mechanism check them, and put them into a
more specific container.

It is not as painful as operation as you might first think. You are
not moving any objects around, just copying 32-bit references. With a
new Map, though you are rebuilding the lookup structure.

If you want to cheat, there may be a way of using type erasure, to
write something with serialisation, then read it back with a more
specific type.

Another approach would be to extend the old class to be generic, using
the original to do the heavy lifting, or write a custom version that
assumes strings, and does the casts for you.
 
P

Patricia Shanahan

Zig said:
I don't think this is the reason. Particularly, making a method
signature generic does not change it's runtime signature.

Even if Properties were made as "Properties extends HashMap<String,String>"
Properties.get will inherit the Map.get signature, which is just:

java/util/Map.get(Ljava/lang/Object;)Ljava/lang/Object;

and thus runtime compatibility is preserved. At the compiler's option,
additional synthetic bridge methods may be created in order to support
covariant return types, but even then, a method with a Ljava/lang/Object
return type must exist at runtime.

Additionally, the parameter "key" of Map.get is not generified: all Maps
accept java.lang.Object as a key, under the premis that if you pass in a
different type then it can't possibly have a previous mapping.

Thus code calling "Properties.get(new Object())" would still be
compatible at compile time.

Lastly, all Strings are assignable as Objects. Thus code calling "Object
x=Properties.get(key)" will also still be compile-time compatible.

I think the real reason Properties does not extend
Hashtable<String,String> is that, while discouraged, it is still valid
to have Properties with non-string key/values. An existing Java 1.4 API
could something like:

public Properties createProps() {
Properties props=new Properties();
props.setProperty("name", "foo");
props.put("version", new Integer());
return props;
}

If this method existed, and you were tasked with calling this method
such as:

Integer version=(Integer) createProps().get("version");

This code would likely not compile in Java 5 if properties was made as
Hashtable<String,String>, and users would be "locked in" to using Java
1.4 as long as they continued to use this API.

HTH,

-Zig

The thing I don't understand is why, before 1.5, Properties extended
anything other than Object. Extending Hashtable or HashMap before
generics created features, such as the ability to add a mapping from an
Integer to a Float, that make no sense for Properties.

Patricia
 
M

Mike Schilling

Patricia said:
The thing I don't understand is why, before 1.5, Properties extended
anything other than Object. Extending Hashtable or HashMap before
generics created features, such as the ability to add a mapping from
an Integer to a Float, that make no sense for Properties.

Presumably someone took a shortcut wthout thinking the consequences
through. It happens :)
 
L

Lasse Reichstein Nielsen

Patricia Shanahan said:
The thing I don't understand is why, before 1.5, Properties extended
anything other than Object. Extending Hashtable or HashMap before
generics created features, such as the ability to add a mapping from an
Integer to a Float, that make no sense for Properties.

Plain bad judgement. "It seemed like a good idea at the time". Joshua
Bloch has said as much in his "Effective Java Language Programming
Guide".

/L
 
M

Mike Schilling

Zig said:
Take a look at the javadocs for Properties.stringPropertyNames(). At
first glance, one expects this method to cast keySet() to a
Set<String>, but note one difference:

"Properties whose key or value is not of type String are omitted"

There may be some other examples, but this was just the first that
caught my eye.

I think this is an indication that, while Properties are *meant* for
Strings, there may be existing code which uses them for other
things.

I think this is axiomatic. If an API is intended to be used for A,
the documentation explains carefully that it's intended for A, and all
the examples show it being used for A, some perverse bastard is going
to use it for B, C, and D, particularly when that's inferior to the
natural ways of doing those.
 
L

Lasse Reichstein Nielsen

Lew said:
Actually, you show a way to abuse Properties. You aren't supposed to use 'put()':

This is what shows that the inheriting from Hashtable is a modelling
error. Properties definitly doesn't satisfy 'is-a Hashtable'.

/L
 
M

Mike Schilling

Lasse said:
This is what shows that the inheriting from Hashtable is a modelling
error. Properties definitly doesn't satisfy 'is-a Hashtable'.

Exactly. Properties may *have* a Hashtable (it was the obvious way to
implement it), but it isn't a Hashtable.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top