Java 从泛型基接口的实例检索类型参数
给定2个接口:Java 从泛型基接口的实例检索类型参数,java,generics,reflection,Java,Generics,Reflection,给定2个接口: public interface BaseInterface<T> { } public interface ExtendedInterface<T0, T1> extends BaseInterface<T0> {} 但是我找不到一种简单的方法可以递归到任何基本泛型接口中,并从中获取任何有意义的内容。我不认为您可以,因为这些接口实际上是特定于实例的,而不是特定于类的。考虑以下事项: List<String> a = new A
public interface BaseInterface<T> { }
public interface ExtendedInterface<T0, T1> extends BaseInterface<T0> {}
但是我找不到一种简单的方法可以递归到任何基本泛型接口中,并从中获取任何有意义的内容。我不认为您可以,因为这些接口实际上是特定于实例的,而不是特定于类的。考虑以下事项:
List<String> a = new ArrayList<String>();
List a=new ArrayList();
字符串列表是通用的,这一事实特定于实例a,而不是类列表。因此,List.class对象的任何方法都不能告诉您泛化类型将是a的String类型。虽然在您的示例中MyClass碰巧为接口的genericized类型设置了值,但我认为这在接口类对象实例中不可用。我认为我能想到的唯一选项是检查由
BaseInterface
声明的通用方法,不被覆盖。我不知道你到底想实现什么,知道什么和不知道什么,但你可以像这样递归到超级界面:
Type[] interfaces = MyClass.class.getGenericInterfaces();
ParameterizedType extInterfaceType = (ParameterizedType)interfaces[0];
Class<?> extInterfaceClass = (Class<?>)extInterfaceType.getRawType();
Type[] baseInterfaces = extInterfaceClass.getGenericInterfaces();
ParameterizedType baseInterfaceType = (ParameterizedType)baseInterfaces[0];
Class<?> baseInterfaceClass = (Class<?>)baseInterfaceType.getRawType();
public interface BaseInterface<T> {
Class<T> getGenericClass();
}
我认为没有一种直接的方法可以获得基本接口的泛型类型
一种方法是在接口中声明如下方法:
Type[] interfaces = MyClass.class.getGenericInterfaces();
ParameterizedType extInterfaceType = (ParameterizedType)interfaces[0];
Class<?> extInterfaceClass = (Class<?>)extInterfaceType.getRawType();
Type[] baseInterfaces = extInterfaceClass.getGenericInterfaces();
ParameterizedType baseInterfaceType = (ParameterizedType)baseInterfaces[0];
Class<?> baseInterfaceClass = (Class<?>)baseInterfaceType.getRawType();
public interface BaseInterface<T> {
Class<T> getGenericClass();
}
我回答我自己的问题时又犯了一次不礼貌的错误 正如gix所指出的,当您开始沿着泛型类型的层次结构前进时,除了第一个层次结构之外,您将丢失有关类型参数的信息 但重要的是:您可以获得要实例化的第一个泛型接口(在我的示例中为ExtendedInterface)的类型参数,还可以获得用于创建子接口的类型参数的名称 因此,通过保持TypeVariable名称到实际类型参数的映射,可以确定基本接口的类型参数 稍后我将使用一些代码进行更新,但它确实有效(您可以从MyClass.class确定用于实例BaseInterface的类型参数) 更新 这是第一次通过一些简单的单元测试。它需要工作。。。真正的问题是,这个问题值得如此可笑的解决方案吗
public class GenericReflectionUtils
{
@SuppressWarnings("unchecked")
public static List<Class> getGenericInterfaceTypeArguments(Class baseInterface, Class concreteClass)
{
if (!baseInterface.isAssignableFrom(concreteClass))
{
throw new IllegalArgumentException("Illegal base interface argument");
}
if (concreteClass.getTypeParameters().length > 0)
{
throw new IllegalArgumentException("Can't determine the type arguments of a generic interface of a generic class");
}
for (Type genericInterface : concreteClass.getGenericInterfaces())
{
List<Class> result = null;
if (genericInterface instanceof Class)
{
result = getGenericInterfaceTypeArguments(baseInterface,(Class)genericInterface);
}
else
{
result = getGenericInterfaceTypeArguments(baseInterface, (ParameterizedType)genericInterface);
}
if (result != null)
{
return result;
}
}
return null;
}
public static Class getClass(Type type)
{
if (type instanceof Class)
{
return (Class) type;
}
if (type instanceof ParameterizedType)
{
return getClass(((ParameterizedType) type).getRawType());
}
if (type instanceof GenericArrayType)
{
Type componentType = ((GenericArrayType) type).getGenericComponentType();
Class<?> componentClass = getClass(componentType);
if (componentClass != null)
{
return Array.newInstance(componentClass, 0).getClass();
}
return null;
}
return null;
}
@SuppressWarnings("unchecked")
private static List<Class> getGenericInterfaceTypeArguments(Class baseInterface, ParameterizedType currentType)
{
Class currentClass = getClass(currentType);
if (!baseInterface.isAssignableFrom(currentClass))
{
// Early out - current type is not an interface that extends baseInterface
return null;
}
Type[] actualTypeArguments = currentType.getActualTypeArguments();
if (currentClass == baseInterface)
{
// currentType is a type instance of the base generic interface. Read out the type arguments and return
ArrayList<Class> typeArgs = new ArrayList<Class>(actualTypeArguments.length);
for (Type typeArg : actualTypeArguments)
{
typeArgs.add(getClass(typeArg));
}
return typeArgs;
}
// currentType is derived
Map<String, Class> typeVarMap = createTypeParameterMap(currentType, null);
for (Type genericInterfaceType : currentClass.getGenericInterfaces())
{
List<Class> result = getGenericInterfaceTypeArguments(baseInterface, (ParameterizedType)genericInterfaceType, typeVarMap);
if (result != null)
{
return result;
}
}
return null;
}
private static Map<String, Class> createTypeParameterMap(ParameterizedType type, Map<String, Class> extendedTypeMap)
{
Map<String, Class> typeVarMap = new HashMap<String, Class>();
Type[] typeArgs = type.getActualTypeArguments();
TypeVariable[] typeVars = getClass(type).getTypeParameters();
for (int typeArgIndex = 0; typeArgIndex < typeArgs.length; ++typeArgIndex)
{
// Does not deal with nested generic arguments...
Type typeArg = typeArgs[typeArgIndex];
if (typeArg instanceof TypeVariable)
{
assert extendedTypeMap != null;
TypeVariable typeVar = (TypeVariable)typeArg;
typeVarMap.put(typeVars[typeArgIndex].getName(), extendedTypeMap.get(typeVar.getName()));
continue;
}
typeVarMap.put(typeVars[typeArgIndex].getName(), getClass(typeArgs[typeArgIndex]));
}
return typeVarMap;
}
private static List<Class> createTypeParameterList(Map<String, Class> typeParameterMap, ParameterizedType type)
{
ArrayList<Class> typeParameters = new ArrayList<Class>(typeParameterMap.size());
for (Type actualType : type.getActualTypeArguments())
{
if (actualType instanceof TypeVariable)
{
// Handles the case when an interface is created with a specific type, rather than a parameter
typeParameters.add(typeParameterMap.get(((TypeVariable)actualType).getName()));
continue;
}
typeParameters.add(getClass(actualType));
}
return typeParameters;
}
@SuppressWarnings("unchecked")
private static List<Class> getGenericInterfaceTypeArguments(Class baseInterface, ParameterizedType currentType, Map<String, Class> currentTypeParameters)
{
Class currentClass = getClass(currentType);
if (!baseInterface.isAssignableFrom(currentClass))
{
// Early out - current type is not an interface that extends baseInterface
return null;
}
if (currentClass == baseInterface)
{
return createTypeParameterList(currentTypeParameters, currentType);
}
currentTypeParameters = createTypeParameterMap(currentType, currentTypeParameters);
for (Type genericInterface : currentClass.getGenericInterfaces())
{
List<Class> result = getGenericInterfaceTypeArguments(baseInterface, (ParameterizedType)genericInterface, currentTypeParameters);
if (result != null)
{
return result;
}
}
return null;
}
公共类GenericReflectionUtils
{
@抑制警告(“未选中”)
公共静态列表getGenericInterfaceTypeArguments(类baseInterface、类concreteClass)
{
如果(!baseInterface.isAssignableFrom(concreteClass))
{
抛出新的IllegalArgumentException(“非法基接口参数”);
}
if(concreteClass.getTypeParameters().length>0)
{
抛出新的IllegalArgumentException(“无法确定泛型类的泛型接口的类型参数”);
}
对于(类型genericInterface:concreteClass.getGenericInterfaces())
{
列表结果=空;
if(类的通用接口实例)
{
结果=getGenericInterfaceTypeArguments(baseInterface,(类)genericInterface);
}
其他的
{
结果=getGenericInterfaceTypeArguments(baseInterface,(ParameterizedType)genericInterface);
}
如果(结果!=null)
{
返回结果;
}
}
返回null;
}
公共静态类getClass(类型)
{
if(类型instanceof Class)
{
返回(类)类型;
}
if(类型instanceof ParameterizedType)
{
返回getClass(((ParameterizedType)类型).getRawType());
}
if(类型instanceof GenericArrayType)
{
类型componentType=((GenericArrayType)类型).getGenericComponentType();
Class componentClass=getClass(componentType);
if(componentClass!=null)
{
返回Array.newInstance(componentClass,0).getClass();
}
返回null;
}
返回null;
}
@抑制警告(“未选中”)
私有静态列表getGenericInterfaceTypeArguments(类baseInterface,ParameterizedType currentType)
{
Class currentClass=getClass(currentType);
如果(!baseInterface.isAssignableFrom(currentClass))
{
//早期输出-当前类型不是扩展baseInterface的接口
返回null;
}
类型[]actualTypeArguments=currentType.getActualTypeArguments();
if(currentClass==baseInterface)
{
//currentType是基本泛型接口的类型实例。读取类型参数并返回
ArrayList typeArgs=新的ArrayList(actualTypeArguments.length);
for(键入typeArg:actualTypeArguments)
{
add(getClass(typeArg));
}
返回typeArgs;
}
//currentType是派生的
Map-typeVarMap=createTypeParameterMap(currentType,null);
对于(类型genericInterfaceType:currentClass.getGenericInterfaces())
{
列表结果=getGenericInterfaceTypeArguments(baseInterface,(ParameterizedType)genericInterfaceType,typeVarMap);
如果(结果!=null)
{
返回结果;
}
}
返回null;
}
私有静态映射createTypeParameterMap(ParameteredType类型,映射扩展类型映射)
{
Map typeVarMap=newhashmap();
Type[]typeArgs=Type.getActualTypeArguments();
TypeVariable[]typeVars=getClass(type).getTypeParameters();
对于(int-typeArgIndex=0;typeArgIndexpublic class MyClass implements ExtendedInterface<String, Object>, BaseInterface<String>{ }
MyClass.class.getGenericInterfaces()[1].getActualTypeArguments()[0]
public class GenericReflectionUtils
{
@SuppressWarnings("unchecked")
public static List<Class> getGenericInterfaceTypeArguments(Class baseInterface, Class concreteClass)
{
if (!baseInterface.isAssignableFrom(concreteClass))
{
throw new IllegalArgumentException("Illegal base interface argument");
}
if (concreteClass.getTypeParameters().length > 0)
{
throw new IllegalArgumentException("Can't determine the type arguments of a generic interface of a generic class");
}
for (Type genericInterface : concreteClass.getGenericInterfaces())
{
List<Class> result = null;
if (genericInterface instanceof Class)
{
result = getGenericInterfaceTypeArguments(baseInterface,(Class)genericInterface);
}
else
{
result = getGenericInterfaceTypeArguments(baseInterface, (ParameterizedType)genericInterface);
}
if (result != null)
{
return result;
}
}
return null;
}
public static Class getClass(Type type)
{
if (type instanceof Class)
{
return (Class) type;
}
if (type instanceof ParameterizedType)
{
return getClass(((ParameterizedType) type).getRawType());
}
if (type instanceof GenericArrayType)
{
Type componentType = ((GenericArrayType) type).getGenericComponentType();
Class<?> componentClass = getClass(componentType);
if (componentClass != null)
{
return Array.newInstance(componentClass, 0).getClass();
}
return null;
}
return null;
}
@SuppressWarnings("unchecked")
private static List<Class> getGenericInterfaceTypeArguments(Class baseInterface, ParameterizedType currentType)
{
Class currentClass = getClass(currentType);
if (!baseInterface.isAssignableFrom(currentClass))
{
// Early out - current type is not an interface that extends baseInterface
return null;
}
Type[] actualTypeArguments = currentType.getActualTypeArguments();
if (currentClass == baseInterface)
{
// currentType is a type instance of the base generic interface. Read out the type arguments and return
ArrayList<Class> typeArgs = new ArrayList<Class>(actualTypeArguments.length);
for (Type typeArg : actualTypeArguments)
{
typeArgs.add(getClass(typeArg));
}
return typeArgs;
}
// currentType is derived
Map<String, Class> typeVarMap = createTypeParameterMap(currentType, null);
for (Type genericInterfaceType : currentClass.getGenericInterfaces())
{
List<Class> result = getGenericInterfaceTypeArguments(baseInterface, (ParameterizedType)genericInterfaceType, typeVarMap);
if (result != null)
{
return result;
}
}
return null;
}
private static Map<String, Class> createTypeParameterMap(ParameterizedType type, Map<String, Class> extendedTypeMap)
{
Map<String, Class> typeVarMap = new HashMap<String, Class>();
Type[] typeArgs = type.getActualTypeArguments();
TypeVariable[] typeVars = getClass(type).getTypeParameters();
for (int typeArgIndex = 0; typeArgIndex < typeArgs.length; ++typeArgIndex)
{
// Does not deal with nested generic arguments...
Type typeArg = typeArgs[typeArgIndex];
if (typeArg instanceof TypeVariable)
{
assert extendedTypeMap != null;
TypeVariable typeVar = (TypeVariable)typeArg;
typeVarMap.put(typeVars[typeArgIndex].getName(), extendedTypeMap.get(typeVar.getName()));
continue;
}
typeVarMap.put(typeVars[typeArgIndex].getName(), getClass(typeArgs[typeArgIndex]));
}
return typeVarMap;
}
private static List<Class> createTypeParameterList(Map<String, Class> typeParameterMap, ParameterizedType type)
{
ArrayList<Class> typeParameters = new ArrayList<Class>(typeParameterMap.size());
for (Type actualType : type.getActualTypeArguments())
{
if (actualType instanceof TypeVariable)
{
// Handles the case when an interface is created with a specific type, rather than a parameter
typeParameters.add(typeParameterMap.get(((TypeVariable)actualType).getName()));
continue;
}
typeParameters.add(getClass(actualType));
}
return typeParameters;
}
@SuppressWarnings("unchecked")
private static List<Class> getGenericInterfaceTypeArguments(Class baseInterface, ParameterizedType currentType, Map<String, Class> currentTypeParameters)
{
Class currentClass = getClass(currentType);
if (!baseInterface.isAssignableFrom(currentClass))
{
// Early out - current type is not an interface that extends baseInterface
return null;
}
if (currentClass == baseInterface)
{
return createTypeParameterList(currentTypeParameters, currentType);
}
currentTypeParameters = createTypeParameterMap(currentType, currentTypeParameters);
for (Type genericInterface : currentClass.getGenericInterfaces())
{
List<Class> result = getGenericInterfaceTypeArguments(baseInterface, (ParameterizedType)genericInterface, currentTypeParameters);
if (result != null)
{
return result;
}
}
return null;
}
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.util.*;
interface BaseInterface<T> {}
interface FirstArg<T1,T2> extends BaseInterface<T1>{}
interface SecondArg<T1,T2> extends BaseInterface<T2>{}
class First implements FirstArg<Number, String> {}
class Second implements SecondArg<Number, String> {}
public class Example {
public static void main(String[] av) {
new Example().go();
}
void go() {
test(First.class);
test(Second.class);
}
void test(Class<?> c1) {
ParameterizedType t2 = (ParameterizedType) c1.getGenericInterfaces()[0];
System.out.println(c1 + " implements " + t2 );
Class<?> c2 = (Class<?>)t2.getRawType();
GenericDeclaration g2 = (GenericDeclaration) c2;
System.out.println(t2 + " params are " + Arrays.asList(g2.getTypeParameters()));
System.out.println("So that means");
for(int i = 0; i<t2.getActualTypeArguments().length; i++) {
System.out.println("Parameter " + c2.getTypeParameters()[i] + " is " + t2.getActualTypeArguments()[i]);
}
ParameterizedType t3 = (ParameterizedType) c2.getGenericInterfaces()[0];
System.out.println(t2 + " implements " + t3);
System.out.println("and so that means we are talking about\n" + t3.getRawType().toString() + " <");
for(int i = 0 ; i< t3.getActualTypeArguments().length; i++) {
System.out.println("\t" + t3.getActualTypeArguments()[i] + " -> "
+ Arrays.asList(g2.getTypeParameters()).indexOf(t3.getActualTypeArguments()[i])
+ " -> " +
t2.getActualTypeArguments()[Arrays.asList(g2.getTypeParameters()).indexOf(t3.getActualTypeArguments()[i])]
);
}
System.out.println(">");
System.out.println();
}
}
Type myType = MyClass.class;
// get the parameterized type, recursively resolving type parameters
Type baseType = GenericTypeReflector.getExactSuperType(myType, BaseInterface.class);
if (baseType instanceof Class<?>) {
// raw class, type parameters not known
// ...
} else {
ParameterizedType pBaseType = (ParameterizedType)baseType;
assert pBaseType.getRawType() == BaseInterface.class; // always true
Type typeParameterForBaseInterface = pBaseType.getActualTypeArguments()[0];
System.out.println(typeParameterForBaseInterface);
}
TypeToken<? extends T> token = TypeToken.of(MyClass.class);
ParameterizedType type =
(ParameterizedType) token.getSupertype(BaseInterface.class).getType();
Type[] parameters = type.getActualTypeArguments();