java的Type设计分析
在1.5
版本后,java设计了Type,但是对于Type是什么一直也是和清晰,所以一起看一下吧。分析的方式采用UML类图的方式,进行功能设计的解释说明。
设计分析
- Type接口
这个接口是所有类型的超类,只有一个没有很大作用的getTypeName()
的默认方法,默认返回toString。 - GenericArrayType接口
是一个数组类型接口,它的元素是ParameterizedType
或者TypeVariable
。只有一个方法,返回数组元素的类型。
举例:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
List<List<String>> strList = new ArrayList<>();
String[] strArr = new String[]{};
// cannot create generic array type but can use field or method get generic type
List<String>[] listArr = new List[1];
listArr[0] = Lists.newArrayList("11");
System.out.println("list===>" + isGenericArrayType(list.getClass().getGenericInterfaces()));
System.out.println("strList===>" + isGenericArrayType(strList.getClass().getGenericInterfaces()));
System.out.println("str==>" + isGenericArrayType(strArr.getClass().getGenericInterfaces()));
System.out.println("listArr==>" + isGenericArrayType(listArr.getClass().getGenericInterfaces()));
Method method = GenericArrayTypeBean.class.getDeclaredMethods()[0];
System.out.println(method);
// public void test(List<String>[] pTypeArray, T[]
// vTypeArray,List<String> list, String[] strings, Person[] ints)
Type[] types = method.getGenericParameterTypes(); // 这是 Method 中的方法
for (Type type : types) {
System.out.println(type instanceof GenericArrayType);// 依次输出true,true,false,false,false
}
}
private static boolean isGenericArrayType(Type[] types) {
return Stream.of(types).anyMatch(type -> type instanceof GenericArrayType);
}
public class GenericArrayTypeBean<T> {
public void test(List<String>[] pTypeArray, T[] vTypeArray,
List<String> list, String[] strings) {
}
}
list===>false
strList===>false
str==>false
listArr==>false
public void com.jd.xstore.stock.center.biz.stock.schedule.JdBuyStockNumChangeSchedule$GenericArrayTypeBean.test(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[])
true
true
false
false
- WilcardType
通配符的类型,经常的用法是?
,? extends
,? super
等。有两个方法,getUpperBounds
和getLowerBounds
-
Type[] getUpperBounds()
返回的是一个上限类型数组。如果没有声明,那么上限是Object
。 -
Type[] getLowerBounds()
返回是一个下限类型数组。没有声明,返回长度为0的数组。
public static void main(String[] args) {
List<? extends String> list = new ArrayList<>();
isWildcardType(list.getClass().getGenericInterfaces());
Field[] declaredFields = GenericBean.class.getDeclaredFields();
Arrays.stream(declaredFields).forEach(field -> {
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
Arrays.stream(((ParameterizedType) genericType).getActualTypeArguments()).forEach(type ->
System.out.println(type.getTypeName() + ": " + (type instanceof WildcardType)));
}
System.out.println(field.getName() + ": " + (genericType instanceof WildcardType));
});
}
private static void isWildcardType(Type[] types) {
for (Type type : types) {
if (type instanceof ParameterizedType) {
Type actualTypeArgument = ((Parameterize dType) type).getActualTypeArguments()[0];
System.out.println(actualTypeArgument.getTypeName() + ": " + (actualTypeArgument instanceof WildcardType));
}
}
}
public class GenericBean {
private List<? extends String> list;
private List<String> strList;
}
E: false
? extends java.lang.String: true
list: false
java.lang.String: false
strList: false
this$0: false
- ParameterizedType
这个是比较常见的类型,但是并没说指定的很明白。个人理解是如果Class可以接受可变类型,这里以T来表示,Class<T>
这种就是参数泛型。
-
Type[] getActualTypeArguments()
获取T的真正类型, -
Type getRawType()
返回Class类型。比如List<String>
返回java.util.List
。
这个示例就略了。上述都有判断ParameterizedType
的。
- TypeVariable
这个官方给的解释很多,我们这里可以理解Class和方法中的T
,V
就是TypeVariable。个人觉得可以理解为类型用来标志泛型的变量,可以有上下限
public static void main(String[] args) {
List<? extends String> list = new ArrayList<>();
isTypeVariable(list.getClass().getGenericInterfaces());
Field[] declaredFields = GenericBean.class.getDeclaredFields();
Arrays.stream(declaredFields).forEach(field -> {
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
Arrays.stream(((ParameterizedType) genericType).getActualTypeArguments()).forEach(type ->
System.out.println(type.getTypeName() + ": " + (type instanceof TypeVariable)));
}
System.out.println(field.getName() + ": " + (genericType instanceof TypeVariable));
});
Method[] methods = GenericBean.class.getMethods();
Arrays.stream(methods).forEach(m -> {
Type[] genericParameterTypes = m.getGenericParameterTypes();
Arrays.stream(genericParameterTypes).forEach(type -> System.out.println(m.getName() + ":" + type.getTypeName() + (type instanceof TypeVariable)));
});
}
private static void isTypeVariable(Type[] types) {
for (Type type : types) {
if (type instanceof ParameterizedType) {
Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0];
System.out.println(actualTypeArgument.getTypeName() + ": " + (actualTypeArgument instanceof TypeVariable));
}
}
}
public class GenericBean<T> {
private List<? extends String> list;
private List<String> strList;
public void test(T t) {
}
public <V> void test2(V v) {
}
}
E: true
? extends java.lang.String: false
list: false
java.lang.String: false
strList: false
this$0: false
test:Ttrue
test2:Vtrue
- GenericDeclaration
A common interface for all entities that declare type variables.
GenericDeclaration接口继承了AnnotatedElement接口,是所有“可以声明(定义)范型变量”的实体的公共接口。也就是说只有实现了这个接口的才能在对应“实体”上声明TypeVariable。目前实现实体有Class
,Method
,Constructor
.
- 只有一个方法
getTypeParameters
获取TypeVariable<?>[]
例子:
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
System.out.println(Arrays.toString(((GenericDeclaration) map.getClass()).getTypeParameters()));
}
[K, V]
Type类型还是很抽象的,还是以后继续了解。资料也不很多。
在梳理的过程中,发现了以下的问题:
Type类型如何获取?
GenericDeclaration是通过获取Class,Method,Constructor的class进行获取的。
GenericArrayType不能直接实例化,只能通过method或者field的genericType进行获取
WildcardType同GenericArrayType
ParameterizedType 是Collection<E>
实现类,实现类的getClass的type就可以。也可以实例化,但是实例化后获取不到对应的泛型,只能获取到泛型变量
TypeVariable 这个是class中才可以获取到的。为什么
List<String>
会instanceofParameterizedType
如何实现的?
待填坑
最后说一句,因为要兼容的原因,Type在运行时会被擦除。就先到这里,各位晚安