Java泛型之Type

2020-10-14  本文已影响0人  code希必地

1、Type

Type是一个接口,是所有类型的父类,下图展示了Type的继承结构:


image.png

可以看到Type的子类有如下几个:

2、ParameterizedType:参数化类型

需要注意的是,并不只是 Collection<String> 才是 parameterized,任何类似于 ClassName<V> 这样的类型都是 ParameterizedType ,比如下面的这些都是 parameterizedType.

Map<String, Person> map;
Set<String> set1;
Class<?> clz;
Holder<String> holder;
List<String> list;

而类似于这样的 ClassName 不是 ParameterizedType。

Set set;
List aList;
T t;

2.1、ParameterizedType 的几个主要方法

1、Type[] getActualTypeArguments()
getActualTypeArguments()获取类型内部的泛型的实际类型,如Map<String,Person> map 返回的是String类型和Person类型组成的Type的数组。
2、Type getRawType()
getRawType()返回原始类型,如 Map<String,Person> map返回的就是Map类型
3、Type getOwnerType()
getOwnerType()获取所有者类型,只有内部类才有所有者,如Map.Entry<String, String> entry 的 getOwnerType() 返回的就是Map类型,而Map<String,String>则返回null。

2.2、Demo

public class ParameterizedTypeTest {

    private Map<String, ParameterizedTypeTest> map;
    private Set<String> set1;
    private Class<?> clz;
    private Holder<String> holder;
    private List<String> list;
    private ArrayList<String> arrayList; 
    private Map.Entry<String, String> entry;

    private String str;
    private Integer i;
    private Set set;
    private List aList;

    static class Holder<V> {
    }

    public static void main(String[] args) {
        Field f = null;
        try {
            // 拿到所有的字段
            Field[] fields = ParameterizedTypeTest.class.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                f = fields[i];


                if (f.getGenericType() instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType();
                    System.out.println(f.getName() + ":");

                    System.out.println("\t ParameterizedType:" + Arrays.asList(parameterizedType.getActualTypeArguments()));
                    System.out.println("\t getRawType:" + parameterizedType.getRawType());
                    System.out.println("\t getOwnerType:" + parameterizedType.getOwnerType());
                }
                // 输出不是ParameterizedType 参数化类型的
                else {
                    System.out.println(f.getName() + ":is not ParameterizedType ");
                }
            }
        } catch (Exception e) {
        }
    }
}

输出:

map:(对应Map<String, ParameterizedTypeTest> map)
     ParameterizedType:[class java.lang.String, class com.fsx.maintest.ParameterizedTypeTest]
     getRawType:interface java.util.Map
     getOwnerType:null
set1:(对应Set<String> set1)
     ParameterizedType:[class java.lang.String]
     getRawType:interface java.util.Set
     getOwnerType:null
clz:(对应Class<?> clz)
     ParameterizedType:[?]
     getRawType:class java.lang.Class
     getOwnerType:null
holder:(对应Holder<String> holder)
     ParameterizedType:[class java.lang.String]
     getRawType:class com.fsx.maintest.ParameterizedTypeTest$Holder
     getOwnerType:class com.fsx.maintest.ParameterizedTypeTest
list:(对应List<String>)
     ParameterizedType:[class java.lang.String]
     getRawType:interface java.util.List
     getOwnerType:null
arrayList:(对应ArrayList<String>)
     ParameterizedType:[class java.lang.String]
     getRawType:class java.util.ArrayList
     getOwnerType:null
entry:(对应Map.Entry<String,String>)
     ParameterizedType:[class java.lang.String, class java.lang.String]
     getRawType:interface java.util.Map$Entry
     getOwnerType:interface java.util.Map
str:is not ParameterizedType 
i:is not ParameterizedType 
set:is not ParameterizedType 
aList:is not ParameterizedType 

2、TypeVariable:类型变量

比如 :
public T t,属于类型变量。t属于类型变量。
public class TypeVariableBean<K extends InputStream & Serializable, V> , K和V都是属于类型变量。
public <T> test(T t){}方法中的<T>以及参数中的T t都属于类型变量。

2.1、TypeVariable的主要方法

2.2、Demo

2.2.1、获取类的泛型类型

先定义一个泛型类

public class TestClass<T> {
}

获取该泛型类的泛型的类型

//获取类的泛型的类型
TypeVariable<Class<TestClass>>[] classVariable = TestClass.class.getTypeParameters();
for (TypeVariable<Class<TestClass>> classTypeVariable : classVariable) {
    Type[] bounds = classTypeVariable.getBounds();
    Class<TestClass> genericDeclaration = classTypeVariable.getGenericDeclaration();
    String name = classTypeVariable.getName();
    System.out.println("上边界:"+Arrays.toString(bounds));
    System.out.println("声明该类型的实体:"+genericDeclaration.getName());
    System.out.println("名称:"+name);
}

输出

上边界:[class java.lang.Object]
声明该类型的实体:com.example.abu.serviceproject.TestClass
名称:T

2.2.2、获取类的属性的泛型类型

在TextClass中声明一个类型变量的属性

public class TestClass<T> {
  private T t;
}

获取属性的泛型类型

try {
        Field field = TestClass.class.getDeclaredField("t");
        Type genericType = field.getGenericType();
        if (genericType instanceof TypeVariable) {
            TypeVariable typeVariable= (TypeVariable) genericType;
            Class genericDeclaration = (Class) typeVariable.getGenericDeclaration();
            Type[] bounds = typeVariable.getBounds();
            String name = typeVariable.getName();
            System.out.println("上边界:"+Arrays.toString(bounds));
            System.out.println("声明该类型的实体:"+genericDeclaration.getName());
            System.out.println("名称:"+name);
        }
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }

输出

上边界:[class java.lang.Object]
声明该类型的实体:com.example.abu.serviceproject.TestClass
名称:T

2.2.3、获取类的方法的泛型类型

在TestClass中创建一个方法

public class TestClass<T> {
    T t;
    public <K> void test(T t, K k) {
    }
}

可以看到这里我们声明了一个泛型方法test(),声明了一个泛型<K>,并且接收两个参数T tK k,这三个都是类型变量类型的,它们有什么区别呢?

Method[] declaredMethods = TestClass.class.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
    //获取方法定义的泛型类型
    TypeVariable<Method>[] typeParameters = declaredMethod.getTypeParameters();
    for (TypeVariable<Method> typeParameter : typeParameters) {
        Method genericDeclaration = typeParameter.getGenericDeclaration();
        Type[] bounds = typeParameter.getBounds();
        String name = typeParameter.getName();
        System.out.println("方法泛型的名称:" + name+":");
        System.out.println("\t方法泛型的上边界:" + Arrays.toString(bounds));
        System.out.println("\t方法中声明该类型的实体:" + genericDeclaration.getName());
    }
    //获取方法参数的泛型类型
    Type[] genericParameterTypes = declaredMethod.getGenericParameterTypes();
    for (Type genericParameterType : genericParameterTypes) {
        if (genericParameterType instanceof TypeVariable) {
            TypeVariable typeVariable = (TypeVariable) genericParameterType;
            GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
            Type[] bounds = typeVariable.getBounds();
            String name = typeVariable.getName();
            System.out.println("方法中参数泛型的名称:" + name + ":");
            System.out.println("\t方法参数中泛型的上边界:" + Arrays.toString(bounds));
            if (genericDeclaration instanceof Class)
                System.out.println("\t方法中参数声明该类型的实体:" + ((Class) genericDeclaration).getName());
            else if (genericDeclaration instanceof Method)
                System.out.println("\t方法中参数声明该类型的实体:" + ((Method) genericDeclaration).getName());
        }
    }
}

输出

方法泛型的名称:K:
    方法泛型的上边界:[class java.lang.Object]
    方法中声明该类型的实体:test
方法中参数泛型的名称:T:
    方法参数中泛型的上边界:[class java.lang.Object]
    方法中参数声明该类型的实体:com.example.abu.serviceproject.TestClass
方法中参数泛型的名称:K:
    方法参数中泛型的上边界:[class java.lang.Object]
    方法中参数声明该类型的实体:test

我们在class TestClass<T>泛型类中声明了一个泛型方法<K> void test(T t, K k)

3、GenericArrayType:泛型数组

GenericArrayType是泛型数组,组成数组的元素中有泛型的数组就是GenericArrayType类型的,组成数组的元素可以是ParameterizedType类型的也可以是TypeVariable类型的。

// 属于 GenericArrayType 组成元素是ParameterizedType 
List<String>[] pTypeArray;
// 属于 GenericArrayType 组成元素是TypeVariable
T[] vTypeArray;
// 不属于 GenericArrayType
List<String> list;
// 不属于 GenericArrayType
String[] strings;
// 不属于 GenericArrayType
Person[] ints;

Demo

public class TestClass<T> {
    T[] t;
    TestClass<T>[] testClassArray;
    List<String>[] listArray;
    String[] strArray;
}

获取类中的属性是否是泛型数组类型,并获取数组中元素的类型。

public void test() {
    Field[] declaredFields = TestClass.class.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        Type genericType = declaredField.getGenericType();
        String fieldName = declaredField.getName();
        if (genericType instanceof GenericArrayType) {
            System.out.println("泛型数组:" + fieldName + ":");
            GenericArrayType genericArrayType= (GenericArrayType) genericType;
            Type genericComponentType = genericArrayType.getGenericComponentType();
            System.out.println("\t泛型数组中元素的类型:"+genericComponentType);
        } else {
            System.out.println("非泛型数组:" + fieldName);
        }
    }
}

输出

泛型数组:t: (对应T[] t)
    泛型数组中元素的类型:T
泛型数组:testClassArray:(对应TestClass<T>[] testClassArray)
    泛型数组中元素的类型:com.example.abu.serviceproject.TestClass<T>
泛型数组:listArray:(对应List<String>[] listArray)
    泛型数组中元素的类型:java.util.List<java.lang.String>
非泛型数组:(对应String[] strArray)strArray

4、WildcardType :通配符类型

<?>、<?extends Number>、<? super Integer>这些都是通配符类型的,extends 用来指定上边界,没有指定的话上边界默认是 Object, super 用来指定下边界,没有指定的话为 null。
几个主要方法介绍

下面一起来看一下例子。

public class WildcardTypeBean<T> {

    private List<? extends Number> a;  // a没有下界,
    //  没有指定的话,上边界默认是 Object ,下边界是  String
    private List<? super String> b;

    private List<String> c;

    private List<T> list;

    private Class<?> aClass;
}

 public void testWildCardType() {
    Field[] fields = WildcardTypeBean.class.getDeclaredFields();
    for (Field field : fields) {
        Type genericType = field.getGenericType();
        if (genericType instanceof WildcardType)
            System.out.println(field.getName() + " is WildcardType");
        else if (genericType instanceof ParameterizedType){
            System.out.println(field.getName() + " is  ParameterizedType");
            ParameterizedType parameterizedType= (ParameterizedType) genericType;
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            Type actualTypeArgument=actualTypeArguments[0];
            if(actualTypeArgument instanceof WildcardType){
                WildcardType wildcardType= (WildcardType) actualTypeArgument;
                System.out.println("-----------------通配符类型-----------------");
                System.out.println("name:"+wildcardType.getTypeName());
                System.out.println("上边界:"+Arrays.toString(wildcardType.getUpperBounds()));
                System.out.println("下边界:"+Arrays.toString(wildcardType.getLowerBounds()));
            }else if(actualTypeArgument instanceof ParameterizedType){
                System.out.println("-----------------参数化类型-----------------");
                System.out.println("name:"+actualTypeArgument.getTypeName());
            }else if(actualTypeArgument instanceof TypeVariable){
                System.out.println("-----------------类型变量-----------------");
                System.out.println("name:"+actualTypeArgument.getTypeName());
            }else if(actualTypeArgument instanceof Class){
                System.out.println("-----------------原始类型-----------------");
                System.out.println("name:"+actualTypeArgument.getTypeName());
            }
        }

    }

}

输出

a is  ParameterizedType
-----------------通配符类型-----------------
name:? extends java.lang.Number
上边界:[class java.lang.Number]
下边界:[]

b is  ParameterizedType
-----------------通配符类型-----------------
name:? super java.lang.String
上边界:[class java.lang.Object]
下边界:[class java.lang.String]

c is  ParameterizedType
-----------------原始类型-----------------
name:java.lang.String

list is  ParameterizedType
-----------------类型变量-----------------
name:T

aClass is  ParameterizedType
-----------------通配符类型-----------------
name:?
上边界:[class java.lang.Object]
下边界:[]
上一篇下一篇

猜你喜欢

热点阅读