Java中字段类型实现接口的通用信息

Generic information about interface implemented by field type in Java

假设我们有一个类型 CustomMap<A, B> 扩展了 CommonMap<C, D> 又实现了 Map<E, F>.

人们自然会期望 A == C == E,但并非总是如此 - 例如,您可以使用 CustomMap<V> 实现 Map<String, V>

问题是,假设我有一个 Fieldfield.getType() 是某个接口或 class 实现 Map<K, V>。类型本身可能是非通用的,可能是通用的但通用签名不同于 <K, V>,等等。我如何使用反射获得 MapKV 类型参数?

看来得写代码爬取类型信息,记住类型参数名对应的类型,然后进行代入。代码可能会根据具体情况有所不同,例如class/interface等,但其核心是:

    // Contains mappings such as K -> Integer, V -> String
    Map<String, Type> typeParameters = new HashMap<>();
    ParameterizedType pType = (ParameterizedType) type;
    // Actual type arguments of a specific parametrized type, e.g. <Integer, PARAM> - 
    // the latter is resolved against typeParameters map
    Type[] typeArguments = pType.getActualTypeArguments();

    cls = ((Class) ((ParameterizedType) type).getRawType());

    // Named arguments of type as declared, e.g. <K, V>
    TypeVariable<?>[] typeParamDecls = cls.getTypeParameters();

    for (int i = 0; i < Math.min(typeParamDecls.length, typeArguments.length); i++) {
        Type value;
        if (typeArguments[i] instanceof TypeVariable) {
            value = typeParameters.get(((TypeVariable<?>) typeArguments[i]).getName());
        } else {
            value = typeArguments[i];
        }

        typeParameters.put(typeParamDecls[i].getName(), value);
    }

这需要递归地应用到 cls.getGenericSuperclass() / cls.getGenericInterfaces() 直到你首先找到你想要的类型。如果在任何地方使用原始类型,可能会出现边缘情况。