繁体   English   中英

为什么要将类的泛型类转换为类 <T> 不安全?

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

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

问题出现在这个构造函数中,它尝试使用签名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> Class<capture#1-of ? extends Object>表示。 我认为,因为从T object参数推断出T的类型,所以调用object.getClass()将返回Class<T>类型的Class对象是必要的 但显然情况并非如此。 有人能解决我的困惑吗?


全类声明和所有构造函数:

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的回答指出object.getClass()衰变为Class<? extends Object> Class<? extends Object> ,解释编译错误。 但是转换为Class<T> 不安全的

getClass “返回它所调用的对象的运行时类”。 例如,如果我们在一个MethodPointer<Number> ,那么object 是一个 Number但它的运行时类型可能是IntegerDouble等。这告诉我们将object.getClass()Class<T>不是安全,因为Class<Integer>Class<Number>是不同的对象,表示不同的类 - 这种区别似乎与您尝试执行的操作的正确性非常相关。

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

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

Javadocs说:

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

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

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

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

Class<?>

为你参数。

所以你的课程有一个未绑定的类型。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM