获取应用了类型参数的已实现接口的Type实例

给定一个Type实例(可能是一个Class或ParameterizedType),我需要获得该类实现的特定类型的接口。 如果没有泛型,这很容易,可以在Class实例上调用getInterfaces()并完成。 然而,即使当实现的接口具有自己的类型参数时,我也需要它来工作,这些类型参数可能取决于原始类本身的类型参数,也可能不取决于类型参数。

一些例子,当给定一个类时,函数应该返回Iterable <Integer>

class Foo implements Iterable<Integer> {}

但是也必须在给定类的情况下返回Iterable <String>

class Bar<T> implements Iterable<T> {}

和表示Bar <String>的ParmeterizedType

有内置反射,第三方工具等的简单方法吗?

为了澄清,这不仅需要通过文本(Foo.class等)检索的类型实例,还需要通过可以包含应用类型参数的反射返回的类型实例,例如通过方法的反射返回的返回类型

static Bar<String> magic() { ... }

这将是引用原始Bar类和String类型参数的ParameterizedType。


您应该看看Google Guava TypeToken类:http://code.google.com/p/guava-libraries/wiki/ReflectionExplained

它提供了用于在各种情况下解决类型的复杂机制。 如果我正确理解你的问题,那么类似于TypeToken#resolveType(Type)方法可能会接近你正在寻找的东西:

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Iterator;

import com.google.common.reflect.TypeToken;

class Foo implements Iterable<Integer> {

    @Override
    public Iterator<Integer> iterator()
    {
        return null;
    }
}

class Bar<T> implements Iterable<T> {

    @Override
    public Iterator<T> iterator()
    {
        return null;
    }
}

public class TypeParameterTest
{
    public static void main(String[] args) throws Exception
    {
        Type i0 = getInterface(Foo.class, 0);
        System.out.println("First interface implemented by Foo: "+i0);

        Method method = TypeParameterTest.class.getDeclaredMethod("magic");
        Type returnType = method.getGenericReturnType();

        System.out.println("Magic method return type: "+returnType);

        Type i1 = getInterface(returnType, 0);
        System.out.println("First interface implemented by Bar<String>: "+i1);
    }

    private static Type getInterface(Type type, int interfaceIndex)
    {
        TypeToken<?> typeToken = TypeToken.of(type);
        Class<?> c = typeToken.getRawType();
        Type[] interfaces = c.getGenericInterfaces();
        if (interfaces.length == 0)
        {
            return null;
        }
        Type i = interfaces[interfaceIndex];
        return typeToken.resolveType(i).getType();
    }

    public static Bar<String> magic() { return null; }
}

这里的输出是

First interface implemented by Foo: java.lang.Iterable<java.lang.Integer>
Magic method return type: Bar<java.lang.String>
First interface implemented by Bar<String>: java.lang.Iterable<java.lang.String>

您可以在类型被硬编码时使用反射,因为它将子类化为特定类型。 这里的类型存储在类信息中。

如果你使用反射,你可以看到Foo扩展了Iterable<String>但是如果你有一个Bar<String>这只是一个Bar在运行时由于类型擦除,所有你看到的是Bar扩展Iterable<T>

如果您有一个参数化的泛型类型,则不会在任何地方记录,因为它在运行时没有任何操作。 如果您需要此类型,则需要将其另存为其他字段。

例如有一个类Collections.CheckedMap,它在运行时检查类型,它像这样开始

private static class CheckedMap<K,V>
    implements Map<K,V>, Serializable
{
    private static final long serialVersionUID = 5742860141034234728L;

    private final Map<K, V> m;
    final Class<K> keyType;
    final Class<V> valueType;

这是一个使用ParameterizedType的例子

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]);
    }
  }
}
链接地址: http://www.djcxy.com/p/57407.html

上一篇: Getting Type instance of implemented interface with type parameters applied

下一篇: Determine if a Class implements a interface in Java