Java中与泛型相关的接口详解

前言

Type

Java 语言中所有类型的公共父接口。 在 JDK1.8 之前是一个空接口,自 JDK1.8 起多了个 getTypeName() 方法。

1
2
3
4
5
6
package java.lang.reflect;
public interface Type {
    default String getTypeName() {
        return toString();
    }
}

Type直接子接口

  • 参数化类型(ParameterizedType): 表示一种参数化的类型,比如 Collection<String>
  • 泛型数组类型(GenericArrayType): 表示一种元素类型参数化类型或者类型变量数组类型
  • 类型变量(TypeVariable): 是各种类型变量公共父接口
  • 通配符类型(WildcardType): 代表一种通配符类型表达式,比如 ?, ? extends Number, ? super Integer

Type直接子类

  • Class类

 

ParameterizedType

源码 ParameterizedType 说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface ParameterizedType extends Type {
    /**
     * 获得<>中实际类型
     * 返回 Map<String, User> 里的 String 和 User,所以这里返回 [String.class, User.clas]
     * */
    Type[] getActualTypeArguments();
	/**
	 * 获得<>前面实际类型
     * Map<String, User> 里的 Map, 所以返回值是 Map.class
     * */
    Type getRawType();
    /**
     * 用于这个泛型上中包含了内部类的情况,一般返回null
     * 如果当前类不是内部类,而是一个顶层类,那么getOwnerType方法将返回null。
     * O<T>.I<S>类型变量调用时会返回 O<T>
     * 比如 Map.Entry<Long,Short> 返回 Map
     * */
    Type getOwnerType();
}
  • getActualTypeArguments
    • 获取“泛型实例”中<>里面的“泛型变量”(也叫类型参数)的值,这个值是一个类型。因为可能有多个“泛型变量”(如:Map<K,V>),所以返回的是一个Type[]。

注意: 无论<>中有几层<>嵌套,这个方法仅仅脱去最外层的<>,之后剩下的内容就作为这个方法的返回值,所以其返回值类型是不确定的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 通过调用 getActualTypeArguments() 方法后返回 ArrayList, Class 类型
List<ArrayList> list;

// 通过调用 getActualTypeArguments() 方法后返回 ArrayList<String>, ParameterizedType 类型
List<ArrayList<String>> list;

// 通过调用 getActualTypeArguments() 方法后返回 T,TypeVariable 类型
List<T> list;

// 通过调用 getActualTypeArguments() 方法后返回 ? extends Number,WildcardType 类型
List<? extends Number> list;

// 通过调用 getActualTypeArguments() 方法后返回 ArrayList<String>[],GenericArrayType 类型
List<ArrayList<String>[]> list;
  • getRawType
    • 返回最外层<>前面那个类型,即Map<K ,V>的Map。
  • getOwnerType
    • 获得这个类型的所有者的类型。这主要是对嵌套定义的内部类而言的,例如于对java.util.Map.Entry<K,V>来说,调用getOwnerType方法返回的就是interface java.util.Map。
    • 如果当前类不是内部类,而是一个顶层类,那么 getOwnerType 方法将返回null。

案例验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class ParameterizedTypeApp<T> {
    private String string;
    private List<ArrayList> list1;
    private List<ArrayList<String>> list2;
    private List<T> list3;
    List<? extends Number> list4;
    List<ArrayList<String>[]> list5;
    Map<String, ? extends Number> map;
    Map.Entry<String, Integer> entry;


    public static void main(String[] args) {
        Field[] declaredFields = ParameterizedTypeApp.class.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            // 获取泛型类型
            Type genericType = declaredField.getGenericType();
            System.out.println("属性名称=" + declaredField.getName());
            if (genericType instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) genericType;
                System.out.println("类型=" + genericType.getTypeName());
                System.out.println("RawType=" + parameterizedType.getRawType());
                System.out.println("OwnerType=" + parameterizedType.getOwnerType());
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                for (int i = 0; i < actualTypeArguments.length; i++) {
                    System.out.println(MessageFormat.format("ActualTypeArguments[{0}]={1}", i, actualTypeArguments[i]));
                }
            } else {
                System.out.println("属性名称=" + declaredField.getName() + "不是参数化类型ParameterizedType");
            }
            System.out.println("-------------------------------");
        }
    }
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
属性名称=string
属性名称=string不是参数化类型ParameterizedType
-------------------------------
属性名称=list1
类型=java.util.List<java.util.ArrayList>
RawType=interface java.util.List
OwnerType=null
ActualTypeArguments[0]=class java.util.ArrayList
-------------------------------
属性名称=list2
类型=java.util.List<java.util.ArrayList<java.lang.String>>
RawType=interface java.util.List
OwnerType=null
ActualTypeArguments[0]=java.util.ArrayList<java.lang.String>
-------------------------------
属性名称=list3
类型=java.util.List<T>
RawType=interface java.util.List
OwnerType=null
ActualTypeArguments[0]=T
-------------------------------
属性名称=list4
类型=java.util.List<? extends java.lang.Number>
RawType=interface java.util.List
OwnerType=null
ActualTypeArguments[0]=? extends java.lang.Number
-------------------------------
属性名称=list5
类型=java.util.List<java.util.ArrayList<java.lang.String>[]>
RawType=interface java.util.List
OwnerType=null
ActualTypeArguments[0]=java.util.ArrayList<java.lang.String>[]
-------------------------------
属性名称=map
类型=java.util.Map<java.lang.String, ? extends java.lang.Number>
RawType=interface java.util.Map
OwnerType=null
ActualTypeArguments[0]=class java.lang.String
ActualTypeArguments[1]=? extends java.lang.Number
-------------------------------
属性名称=entry
类型=java.util.Map$Entry<java.lang.String, java.lang.Integer>
RawType=interface java.util.Map$Entry
OwnerType=interface java.util.Map
ActualTypeArguments[0]=class java.lang.String
ActualTypeArguments[1]=class java.lang.Integer
-------------------------------

 

GenericArrayType

源码 GenericArrayType 说明

1
2
3
4
5
6
public interface GenericArrayType extends Type {
    /**
     * 获取“泛型数组”中元素的类型
    */
    Type getGenericComponentType();
}
  • getGenericComponentType
    • 获取“泛型数组”中元素的类型,要注意的是:无论从左向右有几个[]并列,这个方法仅仅脱去最右边的[]之后剩下的内容就作为这个方法的返回值

案例验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class GenericArrayTypeApp {

    private List<String>[] listArr;
    private List<String>[][] listArrs;

    public static void main(String[] args) throws Exception {
		// 获取 listArr 字段信息
        Field listArrs = GenericArrayTypeApp.class.getDeclaredField("listArr");
		// 获取泛型类型
        Type genericTypes = listArrs.getGenericType();

        System.out.println(genericTypes.getClass().getTypeName());

        GenericArrayType genericArrayTypes = (GenericArrayType) genericTypes;
        System.out.println(genericArrayTypes.getGenericComponentType().getTypeName());


        System.out.println();

		// 获取 listArrs 字段信息
        Field listArr = GenericArrayTypeApp.class.getDeclaredField("listArrs");
		// 获取泛型类型
        Type genericType = listArr.getGenericType();

        System.out.println(genericType.getClass().getTypeName());

        GenericArrayType genericArrayType = (GenericArrayType) genericType;
        System.out.println(genericArrayType.getGenericComponentType().getTypeName());
    }

}

程序运行输出

1
2
3
4
5
sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
java.util.List<java.lang.String>

sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
java.util.List<java.lang.String>[]

 

WildcardType

源码 WildcardType 说明

1
2
3
4
5
6
7
8
9
10
11
public interface WildcardType extends Type {
    /**
     * 获得泛型表达式上界(上限 extends)
     */
    Type[] getUpperBounds();

    /**
     * 获得泛型表达式下界(下限 super)
     */
    Type[] getLowerBounds();
}

案例验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class WildcardTypeApp {
    private Map<? extends String, ? super Number> params;

    public static void main(String[] args) throws Exception {
        Field listArr = WildcardTypeApp.class.getDeclaredField("params");
        // 获取泛型类型
        Type genericType = listArr.getGenericType();

        System.out.println(genericType.getClass().getTypeName());

        ParameterizedType parameterizedType = (ParameterizedType) genericType;

        // 获取泛型变量的信息
        Type[] types = parameterizedType.getActualTypeArguments();

        System.out.println();
        for (int i = 0; i < types.length; i++) {
            Type type = types[i];
            System.out.println(MessageFormat.format("typeName[{0}]={1}", i, type.getTypeName()));

            WildcardType wildcardType = (WildcardType) type;
            for (Type tp : wildcardType.getLowerBounds()) {
                System.out.println(MessageFormat.format("getLowerBounds[{0}]={1}", i, tp.getTypeName()));
            }
            System.out.println();

            for (Type tp : wildcardType.getUpperBounds()) {
                System.out.println(MessageFormat.format("getUpperBounds[{0}]={1}", i, tp.getTypeName()));
            }
            System.out.println();
        }

    }

}

程序运行输出

1
2
3
4
5
6
7
8
9
10
sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl

typeName[0]=? extends java.lang.String

getUpperBounds[0]=java.lang.String

typeName[1]=? super java.lang.Number
getLowerBounds[1]=java.lang.Number

getUpperBounds[1]=java.lang.Object

 

TypeVariable

源码 TypeVariable 说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    /**
     * 获得该“范型变量”的上限(上边界),若无显式定义(extends),默认为Object。
     * 类型变量的上限可能不止一个,因为可以用 & 符号限定多个
     *(这其中有且只能有一个为类或抽象类,且必须放在extends后的第一个,即若有多个上边界,则第一个&后必为接口)
     */
    Type[] getBounds();

    /**
     * 获得声明(定义)这个“范型变量”的类型及名称
     */
    D getGenericDeclaration();

    /**
     * 获得这个“泛型变量”在声明(定义)时候的名称。如:K、V、E等
     */
    String getName();

    /**
     * 
     */
     AnnotatedType[] getAnnotatedBounds();
}

案例验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TypeVariableApp<K extends Integer & Map, V extends List> {
    private K k;
    private V v;

    public static void main(String[] args) throws Exception {
        Type[] types = TypeVariableApp.class.getTypeParameters();

        for (Type type : types) {
            TypeVariable tv = (TypeVariable) type;

            System.out.println("getGenericDeclaration=" + tv.getGenericDeclaration());
            int size = tv.getBounds().length;
            System.out.println("getBounds size=" + size);
            for (Type type1 : tv.getBounds()) {
                System.out.println(type1.getTypeName());
            }
            System.out.println("getName=" + tv.getName());
            System.out.println("-------------分割线-------------\n");
        }

    }
}

程序运行输出

1
2
3
4
5
6
7
8
9
10
11
12
getGenericDeclaration=class com.xiwei.credit.entity.app.TypeVariableApp
getBounds size=2
java.lang.Integer
java.util.Map
getName=K
-------------分割线-------------

getGenericDeclaration=class com.xiwei.credit.entity.app.TypeVariableApp
getBounds size=1
java.util.List
getName=V
-------------分割线-------------

 

使用场景

 

扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class ExpandTypeApp {

    public static void main(String[] args) throws NoSuchMethodException, SecurityException {
        Method method = ExpandTypeApp.class.getMethod("method", String.class, List.class, List.class, List.class, List.class, List.class, Map.class);

        // 按照声明顺序返回 Type 对象的数组
        Type[] types = method.getGenericParameterTypes();

        for (Type type : types) {

            // 参数类型带 <> 的都是 ParameterizedType, 除了 a0 外都是 ParameterizedType
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                System.out.println("参数类型=" + parameterizedType.getTypeName());
                // 返回表示此类型【实际类型参数】的 Type 对象的数组, 去掉最外一层的<>, 即 List<T> 返回 T, Map<K, V> 返回数组 [K, V]
                Type[] tps = parameterizedType.getActualTypeArguments();

                for (int i = 0; i < tps.length; i++) {
                    Type tp = tps[i];
                    System.out.println(MessageFormat.format("index={0}, 类型=[{1}]\t类型接口=[{2}]", i, tp, tp.getClass().getInterfaces()[0]));
                }
            } else {
                System.out.println("我是特殊的=" + type.getTypeName());
            }
            System.out.println("--------------");

        }
    }

    public <T> void method(
            String a0,
            List<String> a1,
            List<ArrayList<String>> a2,
            List<T> a3,
            List<? extends Number> a4,
            List<ArrayList<String>[]> a5,
            Map<String, ? extends Number> a6) { }
}

程序运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
我是特殊的=java.lang.String
--------------
参数类型=java.util.List<java.lang.String>
index=0, 类型=[class java.lang.String]	类型接口=[interface java.io.Serializable]
--------------
参数类型=java.util.List<java.util.ArrayList<java.lang.String>>
index=0, 类型=[java.util.ArrayList<java.lang.String>]	类型接口=[interface java.lang.reflect.ParameterizedType]
--------------
参数类型=java.util.List<T>
index=0, 类型=[T]	类型接口=[interface java.lang.reflect.TypeVariable]
--------------
参数类型=java.util.List<? extends java.lang.Number>
index=0, 类型=[? extends java.lang.Number]	类型接口=[interface java.lang.reflect.WildcardType]
--------------
参数类型=java.util.List<java.util.ArrayList<java.lang.String>[]>
index=0, 类型=[java.util.ArrayList<java.lang.String>[]]	类型接口=[interface java.lang.reflect.GenericArrayType]
--------------
参数类型=java.util.Map<java.lang.String, ? extends java.lang.Number>
index=0, 类型=[class java.lang.String]	类型接口=[interface java.io.Serializable]
index=1, 类型=[? extends java.lang.Number]	类型接口=[interface java.lang.reflect.WildcardType]

 

Reference