Java reflection: Get concrete type of implemented

2020-02-14 01:01发布

Say I have a class like the following

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

Is it possible to get the class object AtomEntry.class from the class object of AtomEntryHandler.class ?

I didn't think it was possible due to erasure, but a friend said it is.

4条回答
我命由我不由天
2楼-- · 2020-02-14 01:32

There is a blog post that goes over it in detail here: Reflecting Generics.

查看更多
该账号已被封号
3楼-- · 2020-02-14 01:37

You can get the generic type for both interfaces and direct subclasses, but only for the concrete implementation. For example, if you have a List<T> instance, you have no way of knowing what it's been parameterized to because of type erasure. If the class definition includes parameterized types that are known at compile time (for example, class StringList extends List<String>) then you can retrieve that information.

ParameterizedType pt = (ParameterizedType)AtomEntryHandler.class.getGenericInterfaces()[0];
Class atomEntryClass = (Class)pt.getActualTypeArguments()[0];
查看更多
叛逆
4楼-- · 2020-02-14 01:37

If you happen to know ConsumingHandler is the only interface AtomEntryHandler implements, and you happen to know it takes just one type argument, you can do this:

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"
    }
}

Otherwise, you can poke around in getGenericInterfaces() and their actualTypeArguments until you find something that looks like what you're looking for.

But if you find yourself needing to do this in real code, either something's probably gone badly wrong in your design, or you're writing some mad genius mock object library and you shouldn't need us to answer these questions.

查看更多
你好瞎i
5楼-- · 2020-02-14 01:43

I could not figure a way to determine base type parameter in case of interface implementation (which does not mean there is none). But this is as close as it gets to it.

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]);
    }
  }
}

Result: class java.lang.Integer

查看更多
登录 后发表回答