获取应用了类型参数的已实现接口的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