Why java.util.Properties implements Map <Object, Object> rather than Map <String, String>

The java.util.Properties class is intended to represent a map, where keys and values โ€‹โ€‹are strings. This is because Properties objects are used to read .properties , which are text files.

So why in Java 5 did they modify this class to implement Map<Object,Object> rather than Map<String,String> ?

javadoc claims:

Because properties inherit from Hashtable, the put and putAll methods can be applied to the Properties object. Their use is highly discouraged since they allow the caller to insert records whose keys or values โ€‹โ€‹are not strings. Instead, use the setProperty method. 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.

Since keys and values โ€‹โ€‹must be strings, why not force it to be set statically using the correct generic type?

I assume that creating Properties implementation of Map<String,String> will not be fully backward compatible with code written for pre-Java 5. If you have older code that binds non-strings to a Properties object, then this code is no longer will compile with Java 5. But ... isn't that good? Didn't all generic points catch such type errors at compile time?

+48
java collections generics
May 16 '09 at 11:17 a.m.
source share
5 answers

Because they were in a hurry in the early days of Java and did not understand what the consequences would be of the four versions later.

From the very beginning, it was assumed that common functions should be part of the Java design, but the function was discarded as being too complex and not needed at that time. As a result, a lot of code in standard libraries was written with the assumption of non-general collections. For the Pizza prototype, Martin Odersky needed a language prototype to show how they could be made quite well, while maintaining almost perfect backward compatibility with Java code and bytecode. The prototype led to Java 5, in which collection classes were modified using generics so that the old code continued to work.

Unfortunately, if they were to retroactively make Properties inherit from Map<String, String> , then the previous valid code will stop working:

 Map<Object, Object> x = new Properties() x.put("flag", true) 

Why would someone do it at ease, but Sun's commitment to backward compatibility in Java has gone beyond the heroic to the meaningless.

What is now appreciated by most educated observers is that Properties should never inherit from Map at all. Instead, it should wrap itself around the Map , displaying only those map features that make sense.

Since the creation of Java, Martin Odersky has continued to create a new Scala language that is cleaner, inherits fewer errors, and breaks new ground in a number of areas. If you find that Java-niggles is annoying, take a look at it.

+48
May 17 '09 at 1:21
source share
โ€” -

It was originally supposed that Properties really extends Hashtable<String,String> . Unfortunately, the introduction of bridge methods has caused a problem. Properties defined this way forces javac to generate synthetic methods. Properties must define, say, a get method that returns a String , but must override a method that returns an Object . Thus, the synthetic bridge method is added.

Suppose you had a class written in the bad old 1.4 days. You have redefined some methods in Properties . But what you have not done yet is overridden by new methods. This leads to inadvertent behavior. To avoid these bridge methods, Properties extends Hashtable<Object,Object> . Similarly, Iterable does not return (read-only) SimpleIterable , because it could add methods to Collection implementations.

+27
May 17 '09 at
source share

Single-line (two-line without warnings) for creating a Map from Properties:

 @SuppressWarnings({ "unchecked", "rawtypes" }) Map<String, String> sysProps = new HashMap(System.getProperties()); 
+13
Mar 18 '11 at 11:59
source share

Backward compatibility.

+4
May 16 '09 at 11:58
source share

Reason: Liskov substitution principle and backward compatibility. Properties extends Hashtable and therefore must accept all messages that the Hashtable will accept, which means accepting put(Object, Object) . And it should extend plain Hashtable instead of Hashtable<String, String> , because Generics were implemented using the down-compatibe method using the erasure type , so once the compiler did its job, there are no generics.

+2
May 16 '09 at 11:36 p.m.
source share



All Articles