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

ast*_*eri 5 java generics casting type-inference

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

问题来自于此构造函数,它试图使用签名调用另一个构造函数MethodPointer(Class<T> clazz, String methodName, Class<?> ... paramClasses):

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

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

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

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

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

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

Unchecked cast from Class<capture#1-of ? extends Object> to Class<T>
Run Code Online (Sandbox Code Playgroud)

我想问题是我不明白是什么Class<capture#1-of ? extends Object>意思.我认为,因为TT object参数推断出类型,调用返回一个类型的对象是必要的.但显然情况并非如此.有人能解决我的困惑吗?object.getClass()ClassClass<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;
    }
Run Code Online (Sandbox Code Playgroud)

Pau*_*ora 6

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

getClass"返回调用它的对象的运行时类".例如,如果我们在a里面MethodPointer<Number>,那么object is-a Number但它的运行时类型可能是Integer,Double等等.这告诉我们,转换object.getClass()Class<T>不安全因为Class<Integer>并且Class<Number>是不同的对象,代表不同的类 - 这种区别似乎非常相关你正在尝试做的正确性.

那么解决方案是什么?好吧,不要施展.坚持Class<T>打电话给来电者.


SLa*_*aks 5

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

Javadoc中说:

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

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

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

  • 不安全并不总是意味着不安全。它真正意味着编译器(受 JLS 约束)无法_确认_类型安全。 (3认同)