The boys at Sun made really an amazing thing when designing Java. I mean, everyone is cursing it now, predicting Java is dead because of its verbosity and such but could those persons have done better? I doubt it. Just consider Java 's penetration in the enterprise… Verbosity enforces readibility, a nice feature in the enterprise where people move from position to position, in and out.
However, I have stumbled upon a troubling quirk. Most Java’s nuts and bolts are enforced at compile time, and erased at runtime. If nothing wrong gets compiled, there’s no reason to check at runtime. The glitch I found compiles fine but throws an exception at runtime.
Consider the following piece of code:
Object[] objects= new String[1];
objects[0] = new Integer(5);
It compiles juts fine but if you execute it, you will be faced with an strange java.lang.ArrayStoreException… Which statement is wrong? Obviously, the first one. How can an array of strings can be considered an array of objects?
Now, I’m not too fond of generics and the convoluted way they are implemented in Java 5 but this particular quirk is not possible with them. None of the two following snippets will compile:
// Type mismatch: cannot convert from ArrayList<String> to List<Object>
List<Object> list = new ArrayList<String>();
List<? extends Object> list = new ArrayList<String>();
// The method add(capture#1-of ? extends Object) in the type
// List<capture#1-of ? extends Object> is not applicable for the arguments (Integer)
list.add(new Integer(3));
For those interested in theory, this behaviour where an array of String
can be seen as an array of Object
is called covariance.
Funny to say it, but Java 5 generics are actually an improvement over array whereas covariance is concerned!
Note that Scala makes arrays nonvariant at compile-time and thus correctly handles the problem:
// type mismatch; found : Array[String] required: Array[java.lang.Object]
var array:Array[Object] = new Array[String](0)