Have we all jumped the gun on Java's implementation of generics?

I’m sure we all remember my angry post about type erasure?
Well I wanted to know more about how Java implements type erasure, so I found this article:
http://today.java.net/pub/a/today/2003/12/02/explorations.html

It’s old, but it effectively mentions that:

[quote]Every type parameter is mapped to the appropriate bound. By this, I mean: the type parameter is erased and replaced with the strongest type the compiler can reasonably assert. Thus, in the case of , T is mapped to Object. In the case of , T is mapped to Rentable, and so on.
[/quote]
So technically, doesn’t this mean that generics DON’T cast at runtime, but at compile time?

However, here is a contradiction:

[quote]Casts are inserted wherever necessary, to ensure that the code compiles.
[/quote]
So from the examples and the like, I figure that if Java can figure out what the type is, it will cast it at runtime and at runtime it will act as though there are no casts.
The only time when generics will force casts at runtime is if Javac can’t find the type.

So would that mean the best way of implementing generics in your code would be to use interfaces?

Of course this doesn’t change the fact you can’t map primitive types. :-\

Generics is just f***ed :P.

I’ve not said anything on it since, but the ACCU conference this year had not one, not two, but three or four (unless there were some others I missed?) sessions explaining in detail how bad they can be (“hopeless” springs to mind), including examples where the statements made in Sun’s docs (e.g. things like “you’ll never have to worry about X happening, this is not possible by design”) were not just mildly inaccurrate but the precise opposite of the truth - and sometimes with supporting commentary for why the implementation choices probably meant this wasn’t an accidental bug but forced in by the core design, and hence hard if not impossible to “fix”.

IIRC you can get hold of the ACCU slides online at the moment, if you search for them, for most talks…so don’t take my word for it (you all know I hate generics anyway :P)

I’ve been using generics very, very heavily for the past 2 months now and I have to say I’m relatively impressed by some of the things that they allow me to express. However the whole concept (and syntax) is quite tricky to grasp and I’m still quite often totally stuck and have to guess my way out of a situation by, say, inserting a ? somewhere or whatever.

The only other real beef I have with generics is that they are not stored as part of the RTTI which means that many nifty optimisations can’t be performed.

That, and the fact that primitive types can’t be used.

Cas :slight_smile:

I think generics makes youre code a bit more understandable and it reduces stupid class cast exception errors, because it just simply wouldn’t parse then.

I’m afraid it’s not making it any more understandable really. When it gets slightly hairy it is very, very difficult to figure out what some things actually mean now, what with all these recursive generics definitions etc.

Cas :slight_smile:

Which was my argument all along, from the very beginning, to all those folks saying “why are you complaining, you don’t have to use these things?”.

It’s just that now I’ve seen how horrible it can (and does) get - and the fact that it even breaks the java compile process! (yes, folks, there’s some decidedly odd hacks Sun added to make generics work. Tis very spooky to see in action - check out the ACCU stuff) - it’s even worse than I thought :(.

You guys obviously know more about this than I do.
I think generics are great when used appropriately.

Can someone give me an example of this horrible mess you guys talking about?

Well, this ain’t very pretty anymore:
private static HashMap<String, Class<? extends Entity>> classmap = new HashMap<String, Class<? extends Entity>>();

But these are quite rare cases (at least for me) and I quite like generics overall.

That’s complex? I’ve used that.


public abstract class CovalentOwnership<T extends CovalentOwnership<T, C>, C extends Covalent<C> & IBaseDataObject<C>> extends BaseOwnership<CovalentOwnershipType, T, C> {....

Amusingly it’s so complicated Eclipse 3.1 RC3 has broken completely.

Cas :slight_smile:

I can read and understand it but I see where the problem is.
Too many generalisations tend to lead you to make wrong assumptions and are very misleading.

[quote] That’s complex? I’ve used that.
[/quote]
Sure it’s not complex but beginning to be ugly to read.

If you have to implement that in the first place, I’d say you’re doing something wrong.
There are no limits or rules on generics.

I’ve used them to accomplish much weirder things.
The entire point is to simplify your code, and that’s what I’m using them for now.

Simplification was never a goal of generics. It was about catching errors earlier, a feat at which it seems to excel. Unfortunately it is at the expense of readability. I don’t really grok generics code at all yet.

Cas :slight_smile:

Hi
I just want to mention that I stumbled on a pretty stupid inconvenience:
java.util.Properties.
Properties is, as anybody knows, some kind of specialized Hashtable. With Generics we could write Properties extends Hashtable<String,String> and that would be exactly what Properties is: a Hashtable that only contains Strings. But if you look into the API Properties does not extend Hashtable<String,String> no - it extends Hashtable<Object,Object> !!! Ok - we could say why use Properties? we’ve got Generics - but the reason for using Properties is the ability of loading and saving Properties to/from a stream. And here it comes: If I want to get all keys from the Properties this code should work, shouldn’t it? (p are my Properties)


Vector<String> keys =  new Vector<String>(p.keySet());

But I can’t, because Properties extends Hashtable<Object,Object> and not Hashtable<String,String>!!
I’ll have to do that:


Vector<String> keys = new Vector<String>();
for(Object o : controllers.keySet()) {
	keys.add((String) o);
}

Arrrghhh!!!

Not exactly. In 1.4 it was possible to store objects as properties (by calling the inherited Hashtable accessors), so I presume the reason for <Object,Object> was backward compatibility.

But you should be able to cast the whole Set


Vector<String> keys = new Vector<String>((Set<String>)p.keySet());

This causes (correctly) an unchecked cast warning which you can hide by annotating the method with @SuppressWarnings(“unchecked”), at least in Eclipse.

I usually like generics very much :stuck_out_tongue: (ok, not in this case g, since I think 99.99% of all usages <1.5 were string properties)

Who cares about generics? They are unneeded. I actually never wrote anything with generics.

Java.util.Properties should be able to work even with 64 bits characters so Object is actually upward compatibile solution.

But all the special functions of Properties work only for Strings. For everything else you could use Hashtable. I think a good solution would be to have

Properties<K,V> extends Hashtable<K,V>

There wouldn’t be then any propblem with downwards compability and I could use Properties<String,String> :wink:

I care about generics, because they have so far trapped at compile time no less than 10 bugs in our code that would only manifest themselves in irritating sneaky rare ways. And I’m getting kinda used to not having to write casts in code now… just need to figure out what arcane combo of ?'s and <>s and extends and supers I need at the top of the class def :wink:

Cas :slight_smile:

I think we would all like to know what those ten were - it would be a lot better than the unsubstantiated opinions and toy examples that are normally quoted both for and against generics.