Hejlsberg Talk About Generics in C# and Java
An anonymous reader writes "artima.com has a very interesting interview with Anders Hejlsberg - the Borland guy now at Microsoft who can best be defined as MR C# - doing all the stuff that Borland wouldn't let him do. He discusses generics in C#, Java (1.5) and C++. Naturally there is the chance of bias but he does raise some interesting points againt Java's generics. Specifically that Java's genericised collections will have to box all primitive types as full objects, whereas C# does not. This is a big performance plus for C#. Java created the primitive types in the first place to address performance concerns but appears to be stepping sideways here. I can't help wondering if Sun has taken this approach to get the syntatic sugar in the language without requiring a bytecode change, but perhaps in a future VM version will allow primitive generics (obvioulsy forcing a bytecode regeneration)?"
Just read a little further into the article. It seems that to avoid having to make changes in the VM, the Java generics have to become just like the current containers at the bytecode level. The main difference would be taht instead of having to type all the ugly type casts yourself, the compiler would do it for you. Obviously, this doesn't lead to any performance increases over Java 1.4 containters.
Compare this to, let's say, C++ templates, where the compiler makes a new copy of the template class specifically for each and every type you use on it. That makes the executable size increase a bunch, but it allows the compiler to pay the performance price, making the code perform almost like a program where a human programmer would have written a copy of the template class for each and every type you ever used it with.
Since the design of the java 1.5 generics is public knowledge, it's pretty easy for anyone with a reasonable programming knowledge to analyze it. It just seems that run-time efficiency wasn't the first thing in the designers minds.
Why have all those 's dirtying up my code, only to enforce strong typing on my collections?
Because compile time errors suck much less than run time errors.
A couple different reasons, actually. First, as mentioned in the article, performance. If you're using generics (come on, call them templates!) and compile-time checking, then you don't need to do the dynamic casting at run-time (c# doesn't, according to the article).
Second, don't scoff at compile-time type checking - I've run into problems on large java projects where there's been some confusion as to what, actually, has been stored in certain collections. Generics prevent this.
It comes down to this: How much help do you, as a programmer, want?
This is just my interpretation. I'm not a C# developer:
Its faster because C# ints don't have to be converted. They are already objects (more like second class structure-like objects). When you define a collection of ints in C#, there is no boxing needed to populate the collection.
You are right about Java, however. The byte code looks the same if you use generics, or not. There won't be any performance loss from old code, just better looking code.
What the article is saying, is that adding primitives to a collection is slower than adding objects (due to boxing - automatic or otherwise). This is supposed to negate the benefits of using primitives (rather than objects) in Java.
The easiest response to that, is the point you just brought up. To get some semblance of compile time type checking, you'd have to make your own type. There are various disadvantages to this, among which are:
As for the benefits of generics, a basic one is that it makes the intent of the code clearer (since you don't want to make a custom type, for the reasons above). The other major one I can come up with right now, is making your interfaces clearer to people who would use your classes. By fully specifying the type (including what is supposed to be in collections), you can make sure the class user is clear on what the interface to a method is, and if he makes a mistake, the compiler will tell him. This means you don't have to deal with all the messy exception handling and such that would go along with just using Object base types.
I am agreed that the < > syntax can be too verbose at times, especially with something like LongClassName<AnotherName> foo = LongClassName<AnotherName>(). Of course, this leaves us with a quandary, since on the one had we want to be able to easily see and specify types of everything, which would suggest using full typenames everywhere. On the other hand, we could introduce typedef like functionality, but that would have some problems of clarity. It seems that Java has historically, and still is taking the first approach.
So there I was, juggling apples and small animals, when I accidentally bit into the wrong one...
I've been reading through the various segments of the interview, and I tend to buy most of what Hejlsberg says on various Java vs. C# issues.
But I keep coming back to the idea that the changes (or improvements) aren't enough. If you accept that all of the changes are improvements, that they make things better, they're still not enough to justify getting locked into a single vendor, or in learning new libraries.
C# cleans up some of Java's annoyances, which is great, but the annoyances just aren't big enough to make the shift worthwhile. That's the problem.
I think the libraries problem is huge for Microsoft. The java libraries are just getting to be so big, complex, and rich that it will be very hard to get people to move away from them.
I don't think that anyone says there aren't annoying things in Java, parts of it that wouldn't be done differently if the language could be redesigned from scratch. But those annoyances are liveable -- for the most part, you can deal with them.
Java's has those libraries, though, and one of the reasons the libraries are so rich is that Sun opened up the process to other companies. MS is huge, they have a lot of smart guys, but I just don't think they can compete with Java's comparative openness.
That's the thing -- you can read about checked exceptions, and agree that it would be nice if java handled things more like C#, but it's not even close to being enough to overcome the value of java's openness vs. Microsoft's closed approach.
In the end, it really comes down to the business model.
C# generics are smart enough to treat value types differently than reference types (or what you're calling a "first class Object"), while Java generics are not.
If strong typing is really important, I can create my own strongly-typed collection.
Sure you can. You can also write the Java bytecode by hand, in hexadecimal, using only your pinky fingers to type.
The point of generics is to reduce (significantly) the amount of time it takes to create strongly typed collections. In addition, it makes those collections more reusable. For example, if I make a strongly typed Iterator, either I have to make an Iterator that doesn't inherit from the java.util.Iterator interface (meaning that it won't be compatable with classes that already use that interface), or I have to create a subclass that has two sets of methods (one strongly and one weakly typed) for every operation. Neither of those options are ideal. Generics provide a 3rd option that is much more elegant and safe.
I mean, how many value types are there already? So you get a couple instantiatians of the class instead of one. And if you are really worried about footprint, you can use only reference types in your list.