Why is casting the class of a generic to Class<T> unsafe?

casting, generics, java, type-inference

Solution

SLaks' answer points out that `object.getClass()` decays to `Class<? extends Object>`, to explain the compile error. But it's not safe to cast to `Class<T>`.

`getClass` "returns the runtime class" of the object it's called on. For example, if we're inside a `MethodPointer<Number>`, then `object` is-a `Number` but its runtime type could be `Integer`, `Double`, etc. That tells us that casting `object.getClass()` to `Class<T>` isn't safe because `Class<Integer>` and `Class<Number>` are different objects, representing different classes - a distinction that seems very relevant to the correctness of what you're trying to do.

So what's the solution? Well, don't cast. Insist on taking a `Class<T>` from the caller.

Problem

I'm making a `MethodPointer` class in order to simulate the functionality of function pointers from C++. At first, I was doing everything with just `Object`s, but then I had a thought -- why not make it truly generic? The problem came in this constructor, which attempted to call another constructor with the signature `MethodPointer(Class<T> clazz, String methodName, Class<?> ... paramClasses)`: ``` public MethodPointer(T object, String methodName, Class<?> ... paramClasses) { this(object.getClass(), methodName, paramClasses); this.object = object; } ``` I assumed this would work just fine, but I received the following compiler error: ``` The constructor MethodPointer<T>(Class<capture#1-of ? extends Object>, String, Class<?>[]) is undefined ``` So, confused, I did this: ``` public MethodPointer(T object, String methodName, Class<?> ... paramClasses) { this((Class<T>) object.getClass(), methodName, paramClasses); this.object = object; } ``` It now compiles, but I receive the following warning: ``` Unchecked cast from Class<capture#1-of ? extends Object> to Class<T> ``` I guess the problem is that I don't understand what `Class<capture#1-of ? extends Object>` means. I thought that since the type of `T` is inferred from the `T object` parameter that it would be necessary that calling `object.getClass()` returns a `Class` object of type `Class<T>`. Apparently this isn't the case, though. Can someone clear up my confusion? Full class declaration and all constructors: ``` public class MethodPointer<T> { //Logger instance private static final Logger LOGGER = Logger.getLogger(MethodPointer.class); //Object fields private final Method method; private ArrayList<Object> args = new ArrayList<Object>(); private T object = null; //Constructors public MethodPointer(Method method) { this.method = method; } public MethodPointer(Class<T> clazz, String methodName, Class<?> ... paramClasses) { Method theMethod = null; try { theMethod = clazz.getMethod(methodName, paramClasses); } catch(NoSuchMethodException nsme) { LogUtil.log(LOGGER, Level.ERROR, "Unable to find method " + methodName + " in " + clazz.getSimpleName(), nsme); } method = theMethod; } public MethodPointer(T object, String methodName, Class<?> ... paramClasses) { this((Class<T>) object.getClass(), methodName, paramClasses); this.object = object; } ```

Original source