推理变量 T 在一种方法中与特定 Class<T> 和实例 <T> 具有不兼容的边界

Már*_*ner 1 java generics extends

我正在使用包含我想使用的方法的库。简化的签名如下所示:

final class ThirdPartyClass
{
    public static <T> void thirdPartyMethod(Class<T> clazz, T instance)
    {
        // does something
    }
}
Run Code Online (Sandbox Code Playgroud)

在它内部thirdPartyMethod(),期望作为T第一个参数,并期望该特定类的实例T作为第二个参数。

现在我有这个简单的抽象类,它正在调用该方法:

abstract class Parent<T extends Number>
{
    public Parent(T instance)
    {
        ThirdPartyClass.thirdPartyMethod(instance.getClass(), instance);
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到错误:

ThirdPartyClass 类中的方法thirdPartyMethod 不能应用于给定类型;
必需:java.lang.Class,T
找到:java.lang.Class<capture#1 of ? extends java.lang.Number>, T
原因:推断变量 T 具有不兼容的边界
等式约束:capture#2 of ? 扩展 java.lang.Number
下界:T

如何修改该类Parent,使其符合预期的参数thirdPartyMethod()?如果可以的话附上解释。

Ale*_*nko 5

根据返回类型Object.getClass()

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

由于Textends Number,结果类型将是Class<? extends Number>ie 意味着未知类型扩展Number。哪个不匹配T extends Number(即扩展将在运行时提供的特定类型)。Number

如何修改 Parent 类,使其符合thirdPartyMethod() 的预期参数?

1.Class<T>在构造函数中引入第二个类型参数。

abstract class Parent<T extends Number> {
    public Parent(T instance, Class<T> tClass) {
        ThirdPartyClass.thirdPartyMethod(tClass, instance);
    }
}
Run Code Online (Sandbox Code Playgroud)

2.执行铸造(如评论中所述):

ThirdPartyClass.thirdPartyMethod((Class<T>) instance.getClass(), instance);
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您可以考虑引入一个工厂方法,该方法将根据方法调用的结果生成域对象,而不是从构造函数调用方法(尤其是那些不是由您/您的同事开发和测试的方法)。