0
点赞
收藏
分享

微信扫一扫

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:kuaidao2022@reworld.com
* 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类型详解​​


举报

相关推荐

0 条评论