为什么要将类的泛型类转换为Class <t> unsafe?</t>

时间:2013-08-12 23:30:42

标签: java generics casting type-inference

我正在创建一个MethodPointer类,以便模拟来自C ++的函数指针的功能。起初,我只用Object s做了所有事情,但后来我想到了 - 为什么不把它变成真正的通用?

这个问题出现在这个构造函数中,它试图调用另一个带有签名MethodPointer(Class<T> clazz, String methodName, Class<?> ... paramClasses)的构造函数:

public MethodPointer(T object, String methodName, Class<?> ... paramClasses) {
    this(object.getClass(), methodName, paramClasses);
    this.object = object;
}

我认为这样可以正常工作,但我收到了以下编译错误:

The constructor MethodPointer<T>(Class<capture#1-of ? extends Object>,
String, Class<?>[]) is undefined

所以,很困惑,我这样做了:

public MethodPointer(T object, String methodName, Class<?> ... paramClasses) {
    this((Class<T>) object.getClass(), methodName, paramClasses);
    this.object = object;
}

它现在编译,但我收到以下警告:

Unchecked cast from Class<capture#1-of ? extends Object> to Class<T>

我想问题是我不明白Class<capture#1-of ? extends Object>的含义。我认为,因为从T参数中推断出T object的类型,所以必需调用object.getClass()会返回Class对象的Class<T>输入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; } 。但显然情况并非如此。有人可以解决我的困惑吗?


完整的类声明和所有构造函数:

{{1}}

3 个答案:

答案 0 :(得分:6)

SLaks的回答指出object.getClass()衰减到Class<? extends Object>,以解释编译错误。但是不安全可以投放到Class<T>

getClass“返回调用它的对象的运行时类”。例如,如果我们在MethodPointer<Number>内,则object 是-a Number,但其运行时类型可以是Integer,{{ 1}}等等告诉我们将Double投射到object.getClass()是不安全的,因为Class<T>Class<Integer>是不同的对象,代表不同的类 - 这似乎是一种区别与你正在尝试做的事情的正确性非常相关。

那么解决方案是什么?好吧,不要施展。坚持从呼叫者那里取一个Class<Number>

答案 1 :(得分:4)

问题是getClass()忽略了类型参数。

Javadocs说:

  

实际结果类型为Class<? extends |X|>,其中|X|是调用getClass的表达式的静态类型的擦除。

例如,new ArrayList<String>().getClass()会返回Class<? extends ArrayList>,而不是Class<? extends ArrayList<String>>

这也意味着调用类型参数的getClass()会衰减为Class<? extends Object>

答案 2 :(得分:0)

如果您不需要指定的Class类型,则可以使用

Class<?>

为你的参数。

所以你的班级有一个未绑定的类型。

如果您想获得一个实例,您可以像这样使用它:

obj.getClass().getDeclaredConstructor(Class<?> parameterTypes)