I was reading about Generics from ThinkingInJava and found this code snippet
public class Erased<T> {
private final int SIZE = 100;
public void f(Object arg) {
if(arg instanceof T) {} // Error
T var = new T(); // Error
T[] array = new T[SIZE]; // Error
T[] array = (T)new Object[SIZE]; // Unchecked warning
}
}
I understand the concept of erasure and I know that at runtime, there is no type for T and it is actually considered an Object (or whatever the upper bound was)
However, why is it that this piece of code works
public class ClassTypeCapture<T> {
Class<T> kind;
public ClassTypeCapture(Class<T> kind) {
this.kind = kind;
}
public boolean f(Object arg) {
return kind.isInstance(arg);
}
}
Shouldn't we apply the same argument here as well that because of erasure we don't know the type of T at runtime so we can't write anything like this? Or am I missing something here?
In your example, T
is indeed erased. But as you pass kind
, which is the class object of the given type, it can be perfectly used for the said check.
Look what happens when you use this class:
ClassTypeCapture<String> capture = new ClassTypeCapture<>(String.class);
Here, the class object of String
is passed to the given constructor, which creates a new object out of it.
During class erasure, the information that T
is String
is lost, but you still have
ClassTypeCapture capture = new ClassTypeCapture(String.class);
so this String.class
is retained and known to the object.