引用内部泛型类型

4

能否提取内部的泛型类型?

假设有以下类:

interface Animal { }

class Bear implements Animal { }

class AnimalRule<ANIMAL extends Animal> { }

class BearRule extends AnimalRule<Bear> { }

现在我想为这段代码编写测试,但我希望有一个通用的基础测试类。
我可以这样声明它:
class AnimalRuleAltTest<ANIMAL extends Animal, RULE extends AnimalRule<ANIMAL>> {
  RULE rule;
  ANIMAL animal;
}

class BearRuleAltTest extends AnimalRuleAltTest<Bear, BearRule> { }

然而我必须同时传递BearBearRule,这似乎是多余的,因为编译器肯定知道BearRule已经实现了AnimalRule<Bear>


如果我只提供规则类,是否有可能提取内部泛型类型?

像这样:

class AnimalRuleTest<RULE extends AnimalRule<ANIMAL>> {
  RULE rule;
  ANIMAL animal;
}

class BearRuleTest extends AnimalRuleTest<BearRule> { }

更新:为了更清楚,我正在询问提取内部类/是否可能,而不是如何“修复”它。

你发布的代码没有展示出你在测试类中如何使用类型参数BearRule。这让我想问为什么不直接将其定义为AnimalRuleAltTest<ANIMAL extends Animal>呢? - ernest_k
@ernest_k 啊,抱歉。我需要在测试中都使用。我已经更新了代码。 - Peter Uhnak
2
我不知道有什么静态/编译时结构能够实现那个。编译器只会为你验证关系,但是在使用它作为变量数据类型之前,你必须静态地声明一个类型(参数)。如果两种类型导致运行时关系,比如组合(像bearRule有一个bear),那么这将是可能的,但是你仍然无法在编译时通过推断类型来声明一个变量。 - ernest_k
我已经成功完成了这个,输出中我得到了一个类对象,这是你想要实现的吗? - Incepter
1
不,你不能在静态环境下查询类型参数。但是,你可以在动态环境下进行查询,就像这个回答中所示。 - fps
显示剩余2条评论
2个回答

0

试试这个:

class AnimalRuleAltTest<ANIMAL extends Animal> {
    AnimalRule<ANIMAL> rule;
    ANIMAL animal;
}

class BearRuleAltTest extends AnimalRuleAltTest<Bear> { }

此外,将AnimalRuleAltTest中所有出现的RULE替换为AnimalRule<ANIMAL>

我知道我可以做到这一点,但原则上与我避免的版本没有什么不同。我想提取内部泛型,而不是引入更多类。 - Peter Uhnak

0

这段代码片段与您的结构完全相同,从 BearRuleTest 转到获取 Bear

public static void main(String...strings) throws Exception {

        final ParameterizedType bearRuleTestGenericSuperclass =
            (ParameterizedType) BearRuleTest.class.getGenericSuperclass();
        final Type type = bearRuleTestGenericSuperclass.getActualTypeArguments()[0];
        final ParameterizedType animalRuleGenericSuperclass =
            (ParameterizedType) Class.forName(type.getTypeName()).getGenericSuperclass();

        System.out.println(
            animalRuleGenericSuperclass.getActualTypeArguments()[0]
        );
    }

编辑:

  • 首先,我获取了您的规则测试通用超类AnimalRuleTest,其中包含一个AnimalRule
  • 然后,我获取第一个参数,即BearRule
  • 我从类加载器中加载BearRule类,然后获取其genericSuperclass,它是带有泛型参数的AnimalRule
  • 然后,我取出第一个参数,即Bear

我认为你误解了问题。OP并不想在运行时动态查找通用类型。相反,他们正在询问是否有一种方法可以不声明最具体测试BearRuleTest(这里将是Bear)中的显式Animal,因为由于其他泛型类型参数(在这种情况下是BearRule,它恰好是一个AnimalRule<Bear>),编译器已经知道了它。 - fps
我明白了,但我仍然不清楚为什么要静态地寻找具体的“Animal”实现,因为我们知道“BearRuleTest”涉及到一只“BEAR”。 - Incepter
OP只是想避免在声明类时额外输入“Bear”作为泛型类型。 - fps

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接