Java类型Api初探

前言

kotlin语言中大量使用泛型相关语法,对于比较抽象的类和函数如果认识仅仅停留在java 实体上,就不能很好的学习kotlin语法的精髓。协程以及compose中泛型相关api比比皆是。不理解java 类型,就不能学好kotlin和compose

秒懂java类型入口

Java 类型参数 说明 示例
Type 所有类型的父类型 -
TypeVariable 类型参数 T t
ParameterizedType 参数化类型 List < T >
GenericArrayType 数组类型 T[ ]
WildcardType 通配符类型 <? extends object>、<? super object>
Class 所有类的类型 object.class

下面是通过 这个TypeTest.class 泛型类,来理解java Type类型的四个关键子类(TypeVariableParameterizedTypeGenericArrayTypeWildcardType )及子类中提供的核心api

/**
 * author:[email protected]
 * data: 2022/7/8 14:46
 * 泛型类,参数为T 和 V
 * java 1.5 引入泛型,目的是运行时可以动态替换泛型参数的类型{对象,属性,[方法形参,返回值]}
 * 泛型实参必须是引用类型 {class,interface,map,int[],set,list}
 * 泛型通配符:
 */
public class TypeTest<T, V extends @Custom Number & Serializable> {
    
    
    private Number number;
    public T t;
    public V v;
    public List<T> list = new ArrayList<>();
    public Map<String, T> map = new HashMap<>();

    //GenericArrayType
    public T[] tArray;
    public List<T>[] ltArray;

    public TypeTest testClass;
    public TypeTest<T, Integer> testClass2;

    public Map<? super String, ? extends Number> mapWithWildcard;

    //泛型构造函数,泛型参数为X
    public <X extends Number> TypeTest(X x, T t) {
    
    
        number = x;
        this.t = t;
    }

    //泛型方法,泛型参数为Y
    public <Y extends T> void method(Y y) {
    
    
        t = y;
    }
}

无论是在java还是Kotlin亦或者其他Jvm语言中,所有声明的可以被jvm识别的类型。均是Type类型的直接子类或者间接子类。最佳实践就是 Retrofit中 CallAdapter.Factory() 响应数据适配,通过 T 进行序列化与反序列化。

Tips: 类型api需要用到反射知识来验证。

TypeVariable

Api 说明 示例
getGenericType() 获取属性类型 V TypeTest.class.getField(“v”).getGenericType()
getBounds() 获取类型变量上界 Arrays.asList(typeVariable.getBounds())
getGenericDeclaration() 获取类型变量声明宿主 TypeTest typeVariable.getGenericDeclaration()
  //通过反射获取 类型参数 public V v;
  private static void mockTypeVariable() {
    
    
        try {
    
    
            System.out.println("****************************TypeVariable************************");
            Field v = TypeTest.class.getField("v");
            TypeVariable typeVariable = (TypeVariable) v.getGenericType();//获取属性类型 V
            System.out.println("TypeVariable1:" + typeVariable);
             //获取类型变量上界,java类中类型可以有多个上界
            System.out.println("TypeVariable2:" + Arrays.asList(typeVariable.getBounds()));
             //获取类型变量声明载体
            System.out.println("TypeVariable3:" + typeVariable.getGenericDeclaration());          
            //1.8 AnnotatedType: 如果这个这个泛型参数类型的上界用注解标记了,我们可以通过它拿到相应的注解
            AnnotatedType[] annotatedTypes = typeVariable.getAnnotatedBounds();
            System.out.println("TypeVariable4:" + Arrays.asList(annotatedTypes) + " : " +
                    Arrays.asList(annotatedTypes[0].getAnnotations()));
            System.out.println("TypeVariable5:" + typeVariable.getName());
        } catch (NoSuchFieldException e) {
    
    
            throw new RuntimeException(e);
        }
    }

ParameterizedType

Api 说明 示例 结果
getActualTypeArguments() 获取参数类型列表 (ParameterizedType)xx.getActualTypeArguments() [class java.lang.String, T]
getRawType() 参数原始类型 - interface java.util.Map
getOwnerType 参数父类型 - null(因为Map没有外部类,所以为null)
//获取 List<T> list、 Map<String, T> map
 private static void mockParameterizedType() {
    
    
        try {
    
    
            //List<T> list
            Field list = TypeTest.class.getField("list");
            //List<T>
            Type genericType1 = list.getGenericType();
            System.out.println("参数类型1:" + genericType1.getTypeName()); //参数类型1:java.util.List<T>

            // Map<String, T> map = new HashMap<>();
            Field map = TypeTest.class.getField("map");
            Type genericType2 = map.getGenericType();
            System.out.println("参数类型2:" + genericType2.getTypeName());//参数类型2:java.util.Map<java.lang.String, T>

            if (genericType2 instanceof ParameterizedType) {
    
    
                ParameterizedType pType = (ParameterizedType) genericType2;
                Type[] types = pType.getActualTypeArguments();
                System.out.println("参数类型列表:" + Arrays.asList(types));//参数类型列表:[class java.lang.String, T]
                System.out.println("参数原始类型:" + pType.getRawType());//参数原始类型:interface java.util.Map
                System.out.println("参数父类类型:" + pType.getOwnerType());//参数父类类型:null,因为Map没有外部类,所以为null
            }
        } catch (NoSuchFieldException e) {
    
    
            throw new RuntimeException(e);
        }
    }

GenericArrayType

    //获取 public T[] tArray;
    private static void mockGenericArrayType() {
    
    
        try {
    
    
            System.out.println("**********************GenericArrayType*********************");
            Field tArray = TypeTest.class.getField("tArray");
            System.out.println("数组参数类型1:" + tArray.getGenericType());
            Field ltArray = TypeTest.class.getField("ltArray");
            System.out.println("数组参数类型2:" + ltArray.getGenericType());//数组参数类型2:java.util.List<T>[]
            if (tArray.getGenericType() instanceof GenericArrayType) {
    
    
                GenericArrayType arrayType = (GenericArrayType) tArray.getGenericType();
                System.out.println("数组参数类型3:" + arrayType.getGenericComponentType());//数组参数类型3:T
            }
        } catch (NoSuchFieldException e) {
    
    
            throw new RuntimeException(e);
        }
    }

WildcardType

Api 说明 示例
getLowerBounds() 获取下界 low = [class java.lang.String]、upper=[class java.lang.Object]
getUpperBounds() 获取上界 low=[ ]、upper=class java.lang.Number
//获取 public Map<? super String, ? extends Number> mapWithWildcard;
    private static void mockWildcardType() {
    
    
        //WildcardType
        try {
    
    
            Field mapWithWildcard = TypeTest.class.getField("mapWithWildcard");
            Type wild = mapWithWildcard.getGenericType();//先获取属性的泛型类型 Map<? super String, ? extends Number>
            if (wild instanceof ParameterizedType) {
    
    
                ParameterizedType pType = (ParameterizedType) wild;
                Type[] actualTypes = pType.getActualTypeArguments();//获取<>里面的参数变量 ? super String, ? extends Number
                System.out.println("WildcardType1:" + Arrays.asList(actualTypes));
                WildcardType first = (WildcardType) actualTypes[0];//? super java.lang.String
                WildcardType second = (WildcardType) actualTypes[1];//? extends java.lang.Number
                System.out.println("WildcardType2: lower:" + Arrays.asList(first.getLowerBounds()) + "  upper:" + Arrays.asList(first.getUpperBounds()));//WildcardType2: lower:[class java.lang.String]  upper:[class java.lang.Object]
                System.out.println("WildcardType3: lower:" + Arrays.asList(second.getLowerBounds()) + "  upper:" + Arrays.asList(second.getUpperBounds()));//WildcardType3: lower:[]  upper:[class java.lang.Number]
            }
        } catch (NoSuchFieldException e) {
    
    
            throw new RuntimeException(e);
        }
    }

引用地址

1.秒懂java类型
2.Java中的Type类型详解

猜你喜欢

转载自blog.csdn.net/o279642707/article/details/125716872