Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does java.util.Properties implement Map<Object,Object> and not Map<String,String>

The java.util.Properties class is meant to represent a map where the keys and values are both Strings. This is because Properties objects are used to read .properties files, which are text files.

So, why in Java 5 did they retrofit this class to implement Map<Object,Object> and not Map<String,String>?

The javadoc states:

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.

Since the keys and values are both supposed to be Strings then why not enforce that statically by using the proper generic type?

I guess making Properties implement Map<String,String> would not be fully backward compatible with code written for pre-Java 5. If you have older code that sticks non-strings into a Properties object then that code would no longer compile with Java 5. But... isn't that a good thing? Isn't the whole point of generics to catch such type errors at compile time?

like image 218
Mike Kucera Avatar asked May 16 '09 23:05

Mike Kucera


People also ask

What is the difference between MAP and properties?

Properties class allows String key/value pairs to read from or write to a stream. You may have have several application specific parameters to be read at the application startup you can utilize Properties class. HashMap is a collection class which allows to use key/value pairs of objects.


1 Answers

Because they did it in a hurry in the early days of Java, and didn't realise what the implications would be four versions later.

Generics were supposed to be part of the design of Java from the beginning, but the feature was dropped as being too complicated and, at the time, unnecessary. As a result, lots of code in the standard libraries is written with the assumption of non-generic collections. It took the prototype language "Pizza" from Martin Odersky to show how they could be done fairly well while maintaining near perfect backwards compatibility, with both Java code and bytecode. The prototype led to Java 5, in which the collections classes were retrofitted with generics in a way that allowed old code to keep working.

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

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

Why anybody would do that is beyond me, but Sun's commitment to backwards compatibility in Java has gone beyond heroic into the pointless.

What's now appreciated by most educated observers is that Properties should never have inherited from Map at all. It should instead wrap around Map, exposing only those features of Map that make sense.

Since reinventing Java, Martin Odersky has gone on to create the new Scala language, which is cleaner, inherits fewer mistakes, and breaks new ground in a number of areas. If you're finding Java's niggles annoying, take a look at it.

like image 54
Marcus Downing Avatar answered Oct 14 '22 01:10

Marcus Downing