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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With