Why is usage of instanceof is not allowed, but Class.isInstance() is allowed in Generics?

alina :

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?

glglgl :

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.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=415500&siteId=1