【问题标题】:How can I get at runtime the type of a wildcard upper bound?如何在运行时获取通配符上限的类型?
【发布时间】:2015-08-28 18:26:46
【问题描述】:

假设我保留了某个类的子类的注册表T

public class ClassRegistry<T> {
    Set<Class<? extends T>> klasses;
    ...
    public void register(Class<? extends T> klass) {
        klasses.add(klass);
    }

您通过registry.register(this.getClass()) 之类的电话注册自己。我想通过 ClassRegistry&lt;T&gt; 上的一个方法让这更简单,你只需传递自己,this,例如,registry.register(this)

    public void register(Object obj) {
        Class<?> klass = obj.getClass();
        this.register(klass);
    }

糟糕,这是错误的,因为它会调用自己(将重载与参数类型 Object 匹配,当然不是 Class&lt;? extends T&gt;)。所以,改为:

    public void register(Object obj) {
        Class<? extends T> klass = obj.getClass();
        this.register(klass);
    }

现在当然不能编译,因为编译器不知道你的obj 实际上是某种类型的? extends T。而且它可能不会,因为调用者可能是错误的。

所以我的问题是:我如何测试/验证 objT 的子类,它是通配符上限(所以我可以安全地转换)? (我怀疑 - 或者也许希望 - 答案涉及 Guava 的 TypeToken,这就是我添加 Guava 标签的原因,但我会接受任何答案,谢谢!)

【问题讨论】:

  • 为什么register 接受Object 而不是T
  • 有趣的想法 - 如果T=Class 怎么办? :)
  • @LouisWasserman - 呃,因为脑子放屁?无论如何,为了知道而忽略它:我仍然想知道它是如何完成的,因为我可能有其他理由知道。

标签: java generics reflection guava type-erasure


【解决方案1】:

您不应该注册任何类型的任何对象,这就是 Object 类型在您的 register 方法中的含义。

我会将该参数的类型更改为T。然后,您可以保证obj.getClass() 将返回Class&lt;? extends T&gt;。编译器不会完全同意这一点,因为Javadocs for getClass() 状态:

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

调用getClass()的结果不是Class&lt;? extends T&gt;,而是Class&lt;? extends Object&gt;T的擦除)。您可以将其转换为 Class&lt;? extends T&gt;,这将生成未经检查的转换警告。但是,因为您现在 objT,所以我认为类型安全性得以保留。

@SuppressWarnings("unchecked")
public void register(T obj) {
    Class<? extends T> klass = (Class<? extends T>) obj.getClass();
    this.register(klass);
}

【讨论】:

  • 或者直接做 - Class klass = obj.getClass();
  • 是的,正如我刚刚回答上面的@LouisWasserman,我把这个简单的问题搞砸了,因为......嗯,它是在午餐前或其他什么时候。您的回答是我编写register 方法的正确方法-但我仍然想知道如何获取上限的类型...
  • @davidbak,答案几乎是你不能因为擦除。
  • @LouisWasserman 啊。我认为可能有某种温和的技巧,例如您通过TypeToken 获取实际类型,但略有不同。但现在我想起你说的话,它真的消失了,不是吗?甚至反思都不会帮助你。哦,好吧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多