0
点赞
收藏
分享

微信扫一扫

Java中的Type

大自然在召唤 2022-04-21 阅读 23
java
public interface Type

在JDK手册中是这样解释的

我们可以看看继承关系 , 它有好多的子接口

Type体系包括原始类型 , 基本类型,数组类型 , 参数化类型 , 类型变量

1.ParameterizedType

表示一个参数化类型,就比如List<T> , Map<k,v>等 , 它包含了三个方法 , 在JDK文档中官方解释是这样的

1.1 getActualTypeArguments()

用下面的代码进行测试

/**
 * @author: Liu Yuehui
 * @ClassName: ParameterizedTypeTest
 * @date: 2022/4/15 10:16
 * @description: 测试  ParameterizedType
 **/
public class ParameterizedTypeTest<T1 , T2> {

    private final List<T1> list = new ArrayList<>();

    private final Map<T1 , T2> map = new HashMap<>();

    private final List<Map<T1, T2>> listMap = new ArrayList<>();

    public static void main(String[] args) {
        ParameterizedTypeTest<String, Number> parameterizedTypeTest = new ParameterizedTypeTest<>();
        Field[] declaredFields = ParameterizedTypeTest.class.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            parameterizedTypeTest.testGetActualTypeArguments(declaredField.getName());
        }
    }

    public void testGetActualTypeArguments(String name){
        try {
            Field list = ParameterizedTypeTest.class.getDeclaredField(name);
            // 获取属性的泛型类型
            Type genericType = list.getGenericType();
            // 获取实际的Type类型 , sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
            System.out.println("获取实际的Type类型 : " + genericType.getClass().getName());

            ParameterizedType listParamType = (ParameterizedType) genericType;

            Type[] listActualTypeArguments = listParamType.getActualTypeArguments();
            for (Type listActualTypeArgument : listActualTypeArguments) {
                System.out.println("当前属性["+name+"]的类型为 : " + listActualTypeArgument);
            }
            System.out.println();

        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

 可以看到都正常的获取到了类型 , 但是listMap和其他获取的不同 , 这是因为复杂类型他只会解析一个<>  , 就比如

解析完之后类型就是Map , 他不会再往里面一层解析 , 解析为T1 , T2  

1.2getRawType

获取<>前得值

1.3getOwnerType

获取泛型得拥有者

以下是完整的测试代码

/**
 * @author: Liu Yuehui
 * @ClassName: ParameterizedTypeTest
 * @date: 2022/4/15 10:16
 * @description: 测试  ParameterizedType
 **/
public class ParameterizedTypeTest<T1 , T2> {

    private List<T1> list;

    private Map<T1 , T2> map;

    private List<Map<T1, T2>> listMap;

    private Map.Entry<T1 , T2> mapEntry;

    public static void main(String[] args) {
        ParameterizedTypeTest<String, Number> parameterizedTypeTest = new ParameterizedTypeTest<>();
        Field[] declaredFields = ParameterizedTypeTest.class.getDeclaredFields();
        Type genericType = null;
        for (Field declaredField : declaredFields) {
            String name = declaredField.getName();
            // 获取属性的泛型类型
            genericType = declaredField.getGenericType();

            ParameterizedType listParamType = (ParameterizedType) genericType;

            // 测试getActualTypeArguments
            parameterizedTypeTest.testGetActualTypeArguments(listParamType , name);
            
            // 测试getRawType
            parameterizedTypeTest.testGetRawType(listParamType , name);
            
            // 测试getOwnerType
            parameterizedTypeTest.testGetOwnerType(listParamType , name);
            System.out.println();
        }

        // 获取实际的Type类型 , sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
        System.out.println("获取实际的Type类型 : " + genericType.getClass().getName());
    }

    public void testGetActualTypeArguments(ParameterizedType listParamType , String name){
        Type[] listActualTypeArguments = listParamType.getActualTypeArguments();
        for (Type listActualTypeArgument : listActualTypeArguments) {
            System.out.println("当前属性["+name+"]的泛型类型为 : " + listActualTypeArgument);
        }
    }

    public void testGetRawType(ParameterizedType listParamType , String name){
        Type rawType = listParamType.getRawType();
        System.out.println("当前属性["+name+"]的类型为 : " + rawType);
    }

    public void testGetOwnerType(ParameterizedType listParamType , String name){
        Type ownerType = listParamType.getOwnerType();
        System.out.println("当前属性["+name+"]泛型的拥有者为 : " + ownerType);
    }
}

测试结果

2.GenericArrayType

表示组件类型是参数化类型或类型变量的数组类型 ,比如T[]

在源码中我们可以看到 , 他只有一个方法

关于这个方法的解释 , 在JDK文档中是这样说的

 接下来用代码体现一下

public class GenericArrayTypeTest<T> {

    private T[] arr;

    private List<String>[] listArray;


    public static void main(String[] args) throws NoSuchFieldException {
        for (Field declaredField : GenericArrayTypeTest.class.getDeclaredFields()) {
            Type type = GenericArrayTypeTest.class.getDeclaredField(declaredField.getName()).getGenericType();
            System.out.println(declaredField.getName() + "字段的类型为 : " +((GenericArrayType)type).getGenericComponentType());
        }
    }
}

测试结果为 :

 3.TypeVariable

在JDK文档中的解释是这样的

 我们可以这么理解: 类型变量的父接口 , 就是泛型里边的类T , E , 即泛型变量

源码:

测试代码:

public class TypeVariableTest<T> {

    T type;

    List<T> typeList;

    public static void main(String[] args) {
        // 获取类上声明的泛型变量 getTypeParameters
        TypeVariable<Class<TypeVariable>> typeVariable = TypeVariable.class.getTypeParameters()[0];
        // 获取泛型变量的上边界 java.lang.reflect.GenericDeclaration
        System.out.println(Arrays.toString(typeVariable.getBounds()));

        // 如果类上申明了泛型
        TypeVariable<Class<TypeVariableTest>> classType = TypeVariableTest.class.getTypeParameters()[0];
        Class<TypeVariableTest> clazzDeclaration = classType.getGenericDeclaration();
        System.out.println(clazzDeclaration);

        // 如果方法上申明了泛型
        Method[] methods = TypeVariableTest.class.getMethods();
        Method method = Arrays.stream(methods)
                .filter(m -> m.getName().equals("test"))
                .collect(Collectors.toList())
                .get(0);
        TypeVariable methodType = (TypeVariable) method.getGenericParameterTypes()[0];
        GenericDeclaration methodDeclaration = methodType.getGenericDeclaration();
        System.out.println(methodDeclaration);

    }

    public <T> void test(T t) {
    }

}

4.WildcardType

表示一个通配符型表达,如 ? , ? extends Number ,或 ? super Integer

源码内部一共有两个方法

这两个方法第一个是用来得到下边界Type的数组 , 第二个就是得到上边界Type得数组

测试代码:

public class WildcardTypeTest {

    // 指定上界 Number,下边界默认为 []
    private List<? extends Number> a;
    // 指定下界 String,上边界默认是 Object
    private List<? super String> b;
    // 上界和下界都不指定,上边界默认是 Object,下边界默认为 []
    private Class<?> clazz;
    // 没有通配符,不是 WildcardType
    private List<String> c;

    public static void main(String[] args) {
        Field[] fields = WildcardTypeTest.class.getDeclaredFields();
        for (Field field : fields) {
            Type genericType = field.getGenericType();
            String name = field.getName();

            if (genericType instanceof ParameterizedType) {
                //2. 再从范型里拿到通配符类型
                ParameterizedType parameterizedType = (ParameterizedType) genericType;
                genericType = parameterizedType.getActualTypeArguments()[0];
                
                if (genericType instanceof WildcardType) {
                    System.out.println("-------------" + name + "--------------");
                    WildcardType wildcardType = (WildcardType) genericType;
                    Type[] lowerTypes = wildcardType.getLowerBounds();
                    if (lowerTypes != null) {
                        System.out.println("上边界:" + Arrays.toString(lowerTypes));
                    }
                    Type[] upTypes = wildcardType.getUpperBounds();
                    if (upTypes != null) {
                        System.out.println("下边界:" + Arrays.toString(upTypes));
                    }
                }
            }
        }
    }

}

 6.GenericDeclaration

GenericDeclaration 该接口用来定义哪些对象上是可以声明范型变量,目前实现 该接口的类包括 Class、Method、Constructor,也就是说只能在这几种对象上进行范型变量的声明(定义)。

它只有一个方法 , 这个方法的作用就是用来逐个获取该 GenericDeclaration 的范型变量声明。

public class GenericDeclarationTest<T> {

    T test;
    
    // 类上声明
    class test<T>{}

    // 构造方法声明
    public <E> GenericDeclarationTest(E e) {

    }

    // 方法声明
    public <K> void test(){

    }

}

JDK中文手册

参考:

JDK 泛型之 Type - binarylei - 博客园

举报

相关推荐

0 条评论