【问题标题】:Java reflection: Get concrete type of implemented generic interfaceJava反射:获取实现的通用接口的具体类型
【发布时间】:2011-10-21 03:21:07
【问题描述】:

假设我有一个像下面这样的课程

public class AtomEntryHandler implements ConsumingHandler<AtomEntry>
{
...
}

是否可以从AtomEntryHandler.class的类对象中获取类对象AtomEntry.class?

由于擦除,我认为不可能,但朋友说是的。

【问题讨论】:

  • 你朋友说的怎么样?
  • Alex Gitelman 的回答对你有用吗?

标签: java generics reflection


【解决方案1】:

您可以获得接口和直接子类的泛型类型,但只能用于具体实现。例如,如果您有一个 List&lt;T&gt; 实例,由于类型擦除,您无法知道它被参数化为什么。如果类定义包含在编译时已知的参数化类型(例如,class StringList extends List&lt;String&gt;),那么您可以检索该信息。

ParameterizedType pt = (ParameterizedType)AtomEntryHandler.class.getGenericInterfaces()[0];
Class atomEntryClass = (Class)pt.getActualTypeArguments()[0];

【讨论】:

  • 我在 doc 中阅读了有关接口的信息,但如果类实现了所讨论的参数化接口(并且没有显式扩展任何类),您将在转换为 ParameterizedType 时收到 java.lang.Object 并转换异常。
  • 如果你调用 getGenericSuperclass() 并且你没有显式扩展任何东西或者你扩展非泛型类,那是真的,但是如果你调用 getGenericInterfaces() 那么类层次结构并不重要,因为它是只处理接口。
【解决方案2】:

在接口实现的情况下,我想不出一种方法来确定基类型参数(这并不意味着没有)。但这已经很接近了。

import java.lang.reflect.*;
public class Foo {
  static class Bar<T> {
  }
  static class SubBar extends Bar<Integer> {
  }

  public static void main(String argv[]) {
    ParameterizedType pt = (ParameterizedType)SubBar.class.getGenericSuperclass();
    Type[] t = pt.getActualTypeArguments();
    for (int i=0;i<t.length;i++) {
       System.out.println(t[i]);
    }
  }
}

结果: class java.lang.Integer

【讨论】:

    【解决方案3】:

    如果您碰巧知道ConsumingHandlerAtomEntryHandler 实现的唯一接口,并且您碰巧知道它只需要一个类型参数,您可以这样做:

    interface ConsumingHandler<T> {}
    
    class AtomEntry {}
    
    class AtomEntryHandler implements ConsumingHandler<AtomEntry>
    {
        public static void main( String[] args )
        {
            Type[] interfaces = AtomEntryHandler.class.getGenericInterfaces();
            ParameterizedType firstInterface = (ParameterizedType) interfaces[0];
            Class c = (Class) firstInterface.getActualTypeArguments()[0];
            System.out.println(c.getName()); // prints "AtomEntry"
        }
    }
    

    否则,您可以在getGenericInterfaces() 和他们的actualTypeArguments 中四处寻找,直到找到看起来像您正在寻找的东西。

    但是,如果您发现自己需要在实际代码中执行此操作,则可能是您的设计出现了严重错误,或者您正在编写一些疯狂的天才模拟对象库,您不应该需要我们回答这些问题。

    【讨论】:

    • 是的,我玩过它,它只是让代码变得比它需要的更复杂。如果它很简单,它会避免一些重复。
    【解决方案4】:

    这里有一篇博客文章详细介绍了它:Reflecting Generics

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      • 2010-09-09
      • 2013-01-18
      • 1970-01-01
      相关资源
      最近更新 更多