Sunday, January 22, 2006

Java Generics Niggle

I've been using Java 5.0 in anger for a while now, and largely I like the extra type safety and (to some extent) expressiveness that the generic types provide, but there are some things that are somewhat annoying. I want to write a test with an assertion that checks the type of the object that I get out of an untyped map - the map is provided by a library class, and can hold different types of objects under different keys, so it can't be parameterised by type. I want to write an assertion something like this (using the JMock assertion syntax):

assertThat(myMap.get(KEY_NAME), isA(List<String>.class));

The immediate problem is that this does not compile. List<String>.class is not valid Java 5.0 syntax. Trying various possibilities, it seems the best I can do is List.class. I also tried new ArrayList<String>().getClass(), which compiles but is unsatisfactory because it is too specific about the class that implements the List, and also, testing shows that the result of executing new ArrayList<String>().getClass() is just ArrayList, not ArrayList<String> as we might hope and expect.

What is going on here? The problem is that generics in Java are a compile time rather than a runtime artifact. When Gilad Bracha was deciding how to implement generics for Java, he decided to take an approach based on Pizza and GJ by Phil Wadler. The compiler takes the parameterisation of types given in the source code, and through a process of erasure uses them to insert the casts that would be needed if we were to write this code under Java 1.4. The effect of this is that in the bytecode, and therefore at runtime, there is no information about type parameters. Hence the problem I showed above, where we are trying to make assertions at runtime.

When Don Syme and Andrew Kennedy implemented generics for .NET, they took a different approach, updating the bytecode instructions in the CLR to allow the generic type information to be held and accessed at runtime. I haven't spent the time to find a neat and elegant way of performing the test that I want, but the documentation gives the impression that it should be possible to create a suitable library method. But I want this in Java, maybe in Mustang...





<< Home

This page is powered by Blogger. Isn't yours?