前言
kotlin语言中大量使用泛型相关语法,对于比较抽象的类和函数如果认识仅仅停留在java 实体上,就不能很好的学习kotlin语法的精髓。协程以及compose中泛型相关api比比皆是。不理解java 类型,就不能学好kotlin和compose
Java 类型参数 | 说明 | 示例 |
---|---|---|
Type | 所有类型的父类型 | - |
TypeVariable | 类型参数 | T t |
ParameterizedType | 参数化类型 | List < T > |
GenericArrayType | 数组类型 | T[ ] |
WildcardType | 通配符类型 | <? extends object>、<? super object> |
Class | 所有类的类型 | object.class |
下面是通过 这个TypeTest.class 泛型类,来理解java Type类型的四个关键子类(TypeVariable、ParameterizedType,GenericArrayType ,WildcardType )及子类中提供的核心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);
}
}