为什么要将泛型的类转换为类< T>不安全? [英] Why is casting the class of a generic to Class<T> unsafe?

查看:202
本文介绍了为什么要将泛型的类转换为类< T>不安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

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



我假设这将正常工作,但我收到以下编译器错误:

 构造函数MethodPointer< T>(Class< capture#1-of?extends Object>,
String, ;>> [])未定义



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

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

 从< capture#1-of类取消选中的投射extends Object>到类< T> 

我想问题是我不明白 Class< capture #1 - 的? extends Object> 表示。我认为由于 T 的类型是从 T对象参数中推断出的, / em> object.getClass()返回的类 T> 。显然不是这样的情况。

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

  public class MethodPointer< T> {

//记录器实例
private static final Logger LOGGER = Logger.getLogger(MethodPointer.class);

//对象字段
private final方法方法;
private ArrayList< Object> args = new ArrayList< Object>();
private T object = null;


//构造方法
public MethodPointer(方法方法){
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,无法在+ clazz.getSimpleName(),nsme中找到方法+ methodName + ;
}
method = theMethod;
}

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


解决方案

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



getClass 返回它所调用的对象的运行时类。例如,如果我们在 MethodPointer< Number> 中,则 object is-a Number ,但其运行时类型可以是 Integer Double 等。这告诉我们,将 object.getClass()转换为类< T> Class< Integer> Class< Number> 是不同的对象,代表不同的类 -



这是什么解决方案?好吧,不要投。坚持从呼叫者接受课堂< T>


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 Objects, 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.

这篇关于为什么要将泛型的类转换为类&lt; T&gt;不安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆