Reputation: 597224
The type erasure page says that
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
However, for the following class:
public class Foo<E extends CharSequence> {
public E something;
}
javap -c Foo
prints:
public class Foo<E extends java.lang.CharSequence> {
public E something;
}
Why is the type parameter not replaced with the bound (CharSequence), but is preserved as E?
Upvotes: 8
Views: 822
Reputation: 317
I agree with @user207421 answer. One can differentiate between raw types and complete generic type by trying out the following code:
public class App {
public static void main(String args[]) {
Foo raw = new Foo(Something);
}
}
When you check the bytecode for this class, you will find that E
is missing. So this is a raw type. These raw types are not bounded and may even require casting due to which Exceptions might be thrown. That is why Generics are used; to ensure type safety. It is a complete source code mechanism.
Upvotes: 0
Reputation: 198211
Type information is preserved on classes and methods, but not on actual fields. If you wrote
class Foo extends Bar<String> {
}
...you could extract Bar<String>
at runtime, but if you had
new Bar<String>();
...you could not extract Bar<String>
there.
Upvotes: 2
Reputation: 116572
The type parameter is preserved because it must be known for sub-classing. Definitions
public class Foo<E extends CharSequence>
and
public class Foo<CharSequence>
are NOT equal, since latter would not allow sub-class to be declared as, say:
public class MyStringFoo extends Foo<String> { }
whereas former does.
Upvotes: -1
Reputation: 310980
What you printed isn't bytecode. It is the method signature. It's put there so the compiler can enforce typesafety when compiling other classes that call it.
Upvotes: 8