簡體   English   中英

如何通過反射來繼承參數化的字段類?

[英]How to get inherited parametrized field class by reflections?

class A extends B<C> {
   ...
}

class B<T extends E> {
   ...
   public D<T> field;
}

如何從“場”反射中獲得“ C”類?

現在,我可以將類“ B”的字段作為“ A”超類的字段,看起來好像他們不知道從“ A”傳遞哪個類型參數,只顯示類型“ E”。

即使A用具體類型C擴展了B ,這也不會改變您從反射中獲得的B場的類型。

但是,您可以手動將字段的type變量映射到具體類型。 首先,為A類構建TypeVariable到具體類型的映射,然后使用該映射將B的類型變量轉換為具體類型。

Class<?> cls = A.class; // using `A` as an example
Class<?> sup = cls.getSuperclass();

 // TypeVariables of `B`
TypeVariable<?>[] tv = sup.getTypeParameters();
 // Concrete types used to extend with in `A`
Type[] actual = ((ParameterizedType) cls.getGenericSuperclass()).getActualTypeArguments();

Map<TypeVariable<?>, Type> mappings // map one to the other
    = IntStream.range(0, tv.length)
        .boxed()
        .collect(Collectors.toMap(i -> tv[i], i -> actual[i]));


for(Field f : sup.getDeclaredFields()) {
    Type t1 = f.getGenericType();
    System.out.println(t1); // prints `D<T>`
    Type t2 = concretify(t1, mappings);
    System.out.println(t2); // prints `D<C>`
}
public static Type concretify(Type from, Map<TypeVariable<?>, Type> mappings) {
    if(from instanceof ParameterizedType) {
        ParameterizedType pt = (ParameterizedType) from;

        Type[] ts = pt.getActualTypeArguments();
        Type[] result = new Type[ts.length];
        for (int i = 0; i < ts.length; i++) {
            result[i] = mappings.getOrDefault(ts[i], ts[i]);
        }

        return new ParameterizedType() { // some ParameterizedType implementation

            @Override
            public Type getRawType() {
                return pt.getRawType();
            }

            @Override
            public Type getOwnerType() {
                return pt.getOwnerType();
            }

            @Override
            public Type[] getActualTypeArguments() {
                return result;
            }

            @Override
            public String toString() {
                return String.format("%s<%s>", getRawType().getTypeName(),
                    Arrays.stream(getActualTypeArguments())
                        .map(Type::getTypeName)
                        .collect(Collectors.joining(",")));
            }
        };
    }
    return from;
}

我實現@JornVernee的想法。

用法:

getFieldsTypesMap(A)

碼:

private static Map<Field, Type> getFieldsTypesMap(Class<?> aClass, Type[] actualTypeParameters) {
    Map<Field, Type> fieldTypeMap = new HashMap<>();
    TypeVariable<? extends Class<?>>[] typeParameters = aClass.getTypeParameters();

    Map<TypeVariable<?>, Type> mappings = new HashMap<>();

    if (typeParameters.length > 0 && actualTypeParameters != null) {
        mappings = IntStream.range(0, typeParameters.length)
                .boxed()
                .collect(Collectors.toMap(i -> typeParameters[i], i -> actualTypeParameters[i]));
    }
    for (Field f : aClass.getDeclaredFields()) {
        if (Modifier.isStatic(f.getModifiers())) {
            continue;
        }
        Type fieldType = getRealFieldType(f.getGenericType(), mappings);
        fieldTypeMap.put(f, fieldType);
    }

    Class<?> superclass = aClass.getSuperclass();
    Type genericSuperclass = aClass.getGenericSuperclass();
    if (genericSuperclass instanceof ParameterizedType) {
        Type[] actual = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
        Type[] remapped = new Type[actual.length];
        for (int i = 0; i < actual.length; i++) {
            remapped[i] = getRealFieldType(actual[i], mappings);
        }
        fieldTypeMap.putAll(getFieldsTypesMap(superclass, remapped));
    } else if (superclass != null) {
        fieldTypeMap.putAll(getFieldsTypesMap(superclass, null));
    }
    return fieldTypeMap;
}

private static Type getRealFieldType(Type from, Map<TypeVariable<?>, Type> mappings) {
    if(from instanceof ParameterizedType) {
        ParameterizedType parameterizedType = (ParameterizedType) from;

        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        Type[] result = new Type[actualTypeArguments.length];
        for (int i = 0; i < actualTypeArguments.length; i++) {
            result[i] = getRealFieldType(mappings.getOrDefault(actualTypeArguments[i], actualTypeArguments[i]), mappings);
        }

        return new ParameterizedType() {

            @Override
            public Type getRawType() {
                return parameterizedType.getRawType();
            }

            @Override
            public Type getOwnerType() {
                return parameterizedType.getOwnerType();
            }

            @Override
            public Type[] getActualTypeArguments() {
                return result;
            }

            @Override
            public String toString() {
                return String.format("%s<%s>", getRawType().getTypeName(),
                        Arrays.stream(getActualTypeArguments())
                                .map(Type::getTypeName)
                                .collect(Collectors.joining(",")));
            }
        };
    }
    return mappings.getOrDefault(from, from);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM