范型的使用

112 阅读2分钟

问题是什么

开发中经常会用到范型配合设计模式来封装相同的代码逻辑。但是在具体的代码实现中,有可能需要去获取范型的具体类型Class来处理(比如反射操作),如何在代码中获取到范型的具体类型呢?

获取范型的具体类型

/**
 * 获取 T.class
 */
protected Class<P> getTClass() {
    return (Class<P>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

getlClass()


/**
 * Returns the runtime class of this {@code Object}. The returned
 * {@code Class} object is the object that is locked by {@code
 * static synchronized} methods of the represented class.
 *
 * <p><b>The actual result type is {@code Class<? extends |X|>}
 * where {@code |X|} is the erasure of the static type of the
 * expression on which {@code getClass} is called.</b> For
 * example, no cast is required in this code fragment:</p>
 *
 * <p>
 * {@code Number n = 0;                             }<br>
 * {@code Class<? extends Number> c = n.getClass(); }
 * </p>
 *
 * @return The {@code Class} object that represents the runtime
 *         class of this object.
 * @jls 15.8.2 Class Literals
 */
public final native Class<?> getClass();

这里是获取当前类的Class。注意这里返回的是Class

getGenericSuperclass()

public Type getGenericSuperclass() {
    ClassRepository info = getGenericInfo();
    if (info == null) {
        return getSuperclass();
    }

    // Historical irregularity:
    // Generic signature marks interfaces with superclass = Object
    // but this API returns null for interfaces
    if (isInterface()) {
        return null;
    }

    return info.getSuperclass();
}

这里是获取父类的Class,包含范型参数,注意这里返回的Type。后面会讲Class和Type的区别,(ParameterizedType) getClass().getGenericSuperclass()代码中这里的Type会强转为ParameterizedType。ParameterizedType 表示参数化范型,这里是类似List<T> 或者 AbstractExcelImportService<P>(其中AbstractExcelImportService是代码里的自定义类)

getActualTypeArguments()

    /**
     * Returns an array of {@code Type} objects representing the actual type
     * arguments to this type.
     *
     * <p>Note that in some cases, the returned array be empty. This can occur
     * if this type represents a non-parameterized type nested within
     * a parameterized type.
     *
     * @return an array of {@code Type} objects representing the actual type
     *     arguments to this type
     * @throws TypeNotPresentException if any of the
     *     actual type arguments refers to a non-existent type declaration
     * @throws MalformedParameterizedTypeException if any of the
     *     actual type parameters refer to a parameterized type that cannot
     *     be instantiated for any reason
     * @since 1.5
     */
    Type[] getActualTypeArguments();

这里是返回ParameterizedType中的<>里面的具体参数类型,比如List<T>这里会返回T的具体类型;AbstractExcelImportService<P>这里会返回P的具体类型;Map<K,V>这里会返回K和V的具体类型,由于<>中可以有多个范型,所以返回的是Type数组。这里需要注意的是,这个方法只会返回最外层<>里面的参数类型,嵌套的<>不会返回。

public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement 

Class继承了Type,所以最后可以直接强转为Class。