For the following 2 classes detailed below:
class Gen<T> {
T ob;
Gen(T o) {
ob = o;
}
// Return ob.
T getob() {
return ob;
}
}
class Gen2<T> extends Gen<T> {
Gen2(T o) {
super(o);
}
}
class HierDemo3 {
public static void main(String args[]) {
// Create a Gen2 object for Integers.
Gen2<Integer> iOb2 = new Gen2<Integer>(99);
if(iOb2 instanceof Gen2<Integer>) //compile-time error
System.out.println("iOb2 is instance of Gen2<Integer>");
}
}
I know very well that it will compile for:
iOb2 instanceof Gen2<?>
Sounds like there is no generic type information available at run time. If so, when is it made available? I am confused...
At the end of compilation, type erasure occurs, and type information such as this is not present in the generated bytecode. This occurs because Java needs to maintain backwards compatibility with code that was written pre-Generics. The JVM has no notion of generics.
Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to:
- 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.
- Insert type casts if necessary to preserve type safety.
- Generate bridge methods to preserve polymorphism in extended generic types. Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.
The instanceof
operator is inherently a runtime operation, so it cannot determine what the generic type parameter is, so the compiler must disallow generic types for instanceof
.
Using Gen2<?>
or just Gen2
is the best you can do at runtime.