|
Monday, December 10, 2007
From C# to Java: Part 5
In the transition from C# 1.0 to C# 2.0, they added
generics. This was an enormous improvement. Huge.
(At first I was actually kind of skeptical of generics.
They reminded me of C++ templates, the use of which I had opposed on several
occasions. But my 1993 reasons for advocacy against C++ templates really
weren't relevant to the C# generics in 2005.)
So when I started my recent exploration of Java, one of my
main questions was: Are the generics in Java 1.5 similar to generics in C#
2.0?
The answer: Sort of. Not really.
To be fair, I'll admit right up front that Java generics are
better than no generics. I'm using them. They work just fine in practice for
most situations.
But they're fundamentally different from C# generics. In
C#, a generic is implemented at the CLR level. When you instantiate a
List<T>, at runtime it will generate an implementation of a List which is
specifically for type T.
When TPTB added generics to Java, one of their goals was to
avoid the need for any changes to the VM. So Java's generics are implemented
at the compiler level using a technique called "type erasure". Basically, the
Java compiler does all the necessary type checking, but then it throws the
parameterized type information away and generates regular collection code.
This has a few consequences which are rather unfortunate:
- Since the parameterized type is no longer present in the
bytecode, reflection doesn't show it.
- The compiler inserts all the casts that you would have had
to write if you were using the non-generic collection class directly.
- In a generic collection of a primitive type, the
parameterized type gets boxed.
So Java's generics are a nice convenience for the
programmer, but they don't bring any of the performance benefits which we get
from generics in C#.
Note that these tradeoffs were not accepted with no gain.
The primary motivation here was to get generics without sacrificing backward
compatibility. That's an important consideration, especially given the amount
of Java code that already existed prior to 1.5.
But if you're coming from C# 2.0 to Java, it's good to
understand how generics are different.
(For a more authoritative discussion of the topic, check out
Bruce Eckel's interview with Anders
Hejlsberg.)
|