java的Type设计分析

1.5版本后,java设计了Type,但是对于Type是什么一直也是和清晰,所以一起看一下吧。分析的方式采用UML类图的方式,进行功能设计的解释说明。

设计分析

java Get方式用实体接参 java gettype_System

  1. Type接口
    这个接口是所有类型的超类,只有一个没有很大作用的getTypeName()的默认方法,默认返回toString。
  2. 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
  1. WilcardType
    通配符的类型,经常的用法是?,? extends,? super等。有两个方法, getUpperBoundsgetLowerBounds
  • 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
  1. ParameterizedType
    这个是比较常见的类型,但是并没说指定的很明白。个人理解是如果Class可以接受可变类型,这里以T来表示,Class<T>这种就是参数泛型。
  • Type[] getActualTypeArguments()获取T的真正类型,
  • Type getRawType() 返回Class类型。比如List<String>返回java.util.List

这个示例就略了。上述都有判断ParameterizedType的。

  1. 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
  1. 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>会instanceof ParameterizedType 如何实现的?
待填坑

最后说一句,因为要兼容的原因,Type在运行时会被擦除。就先到这里,各位晚安