Yeah but the thread is about types, not generic types specifically.
Also it’s not really true that genetics are erased. There’s that horrible thing javac does so that the VM can support reflection for generics. I get your point though.
Do you mean the passing of classes as additional arguments? I haven't seen the horrible thing.
Overall I think C# got this one right. Generics are right there in the binaries.
bUt ActuALLy, I think the rightest right thing is to do specialization up to representation at link time (or compile time), when the whole program is available, ala MLton. Virgil does this. Of course this is not possible in a dynamic code loading environment but I only have so many fucks to give in this life.
No, I meant that the Class format has metadata about what the genetics were so some java.lang.reflect thing can query about what the genetic type was. I don’t think it comes with soundness guarantees.
I agree C# got this right.
I agree that doing specialization up to link time is ideal from a certain standpoint.
All generics in Java are of type Object from the start, you can't call any methods on them not implemented by Object. So it is wrong to say they are erased, they were never there to start with.
You can add a constraint to a generic declaration, which is an upper (or lower) bound on the allowable type arguments.
e.g.
class A<Y extends X> {
// in this scope, Y is known to be of at least type X,
// so, we can call methods on expressions of type Y
// that belong to type X (and not Object)
Y m() { ... }
}
Type arguments are omitted from usage sites. The technique is literally called erasure in papers and documentation.
a = new A<Foo>();
f = a.m(); // should return a Foo, in bytecode returns Y
// and compiler inserts a cast from Y -> Foo
Generic code is slower in Java because of these extra casts. To get back (most of) the performance, the JVM has to inline enough methods to be able to track the types from start to finish. It can't always.
And that's why Java is slower than it could be. If I'm using String[] array, it can't contain anything but String objects, so JVM does not have to check type everytime I'm accessing that array. That's not true for ArrayList<String>, where compiler must check returned object type from `get(index)` (because it really is Object and can contain anything), but it could be true with better language design.