栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java 反射概览: 泛型 Type

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java 反射概览: 泛型 Type

文章目录
  • 产生背景
  • Type类图
  • ParameterizedType
    • 参数化
    • 方法
      • Type[] getActualTypeArguments()
      • Type getRawType();
      • Type getOwnerType();
  • GenericArrayType
    • 方法
      • getGenericComponentType
  • TypeVariable
    • 方法
      • getBounds()
      • getGenericDeclaration()
      • getName()
  • WildcardType
    • 方法

产生背景

泛型信息在运行时将会被擦除,Type的引入使得开发者在程序运行期内获取属性或者类的具体声明成为可能。

Type类图 ParameterizedType

英文直译为参数化类型,有的人看到参数化类型就蒙了:和泛型有什么关系?其实参数化类型就是泛型,不要被不同的翻译误导了。

参数化

理解参数化类型,先要了解参数化:

假如我有一个边长是4的正方形,计算正方形的面积:4x4 = 16。如果边长变成了3,面积就是3x3 = 9。这时候来了一个聪明人,说我们可以用a代表正方形的边长,所有正方形的边长就是a x a。不管a是多少,只要带入公式就能得到面积。用a代表边长的方式,就称为参数化,具体点可以称为参数化边长。

这时候再来理解参数化类型就方便了,我可以随便定义一个符号代表类型。List中用的是E,Map用的是K和V。所以参数化类型,就是我们经常使用的泛型。

public interface List extends Collection
public interface Map 

然后我们看一看C类中,哪个字段的类型是ParameterizedType

 public class C {
      private List list;
      private Map map;
      private Class aClass;
      private Bean bean;
      private List list_1;

      public class Bean {

      }
 }

结合对参数化的理解,C类中除了list_1,其他字段的类型都是ParameterizedType:

@Test
public void parameterizedTypeInClass(){
    Class c = C.class;
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        System.out.println(field.getName() + " is ParameterizedType : "+ (field.getGenericType() instanceof ParameterizedType));
    }
}
list is ParameterizedType : true
map is ParameterizedType : true
aClass is ParameterizedType : true
bean is ParameterizedType : true
list_1 is ParameterizedType : false
方法 Type[] getActualTypeArguments()

获取参数的实际类型,说通俗点,就是尖括号<>中的类型

public void getActualTypeArguments(){
    Class c = C.class;
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        if(field.getGenericType() instanceof ParameterizedType){
            ParameterizedType genericType = (ParameterizedType) field.getGenericType();
            System.out.println(field.getName() + " : "+ Arrays.toString(genericType.getActualTypeArguments()));
        }
    }
}
list : [class java.lang.String]
map : [class java.lang.String, class java.lang.Integer]
aClass : [?]
bean : [class java.lang.String]
Type getRawType();

返回表示声明此类型的类或接口的Type对象。简单说就是字段基本类型。

@Test
public void getRawType(){
    Class c = C.class;
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        if(field.getGenericType() instanceof ParameterizedType){
            ParameterizedType genericType = (ParameterizedType) field.getGenericType();
            System.out.println(field.getName() + " : "+ genericType.getRawType());
        }
    }
}
list : interface java.util.List
map : interface java.util.Map
aClass : class java.lang.Class
bean : class com.example.myapplication.type.TestParameterizedType$C$Bean
Type getOwnerType();

Owner的意思是拥有者。如果一个类属于其他了,会返回声明内部类的类,如果不是内部类,则返回null。

@Test
public void getOwnerType(){
    Class c = C.class;
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        if(field.getGenericType() instanceof ParameterizedType){
            ParameterizedType genericType = (ParameterizedType) field.getGenericType();
            System.out.println(field.getName() + " : "+ genericType.getOwnerType());
        }
    }
}

Bean是C类中的内部类,因此Bean的拥有者Owner是C。

list : null
map : null
aClass : null
bean : class com.example.myapplication.type.TestParameterizedType$C
GenericArrayType

泛型数组

class A {
    T[] arr;
}

@Test
class A {
    T[] arr;
    String[] arrString;
}

@Test
public void testGeneric(){
    Class aClass = A.class;
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        Type genericType = declaredField.getGenericType();
        System.out.println(declaredField.getName() + " : "+(genericType instanceof GenericArrayType));
    }

}
arr : true
arrString : false
方法 getGenericComponentType

返回数组的类型

@Test
public void getGenericComponentType(){
    Class aClass = A.class;
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        Type genericType = declaredField.getGenericType();
        if (genericType instanceof GenericArrayType) {
          System.out.println("getGenericComponentType:"+((GenericArrayType) genericType).getGenericComponentType());
        }
    }
}
getGenericComponentType:T
TypeVariable

类型变量,使用泛型时,常用的大写替代字母,属于这种类型。

//B类声明了2个泛型,即两个TypeVariable
public class B {
    List list;
    Map map;
    E e;
    public E method(E e){
        return e;
    }
}
@Test
public void TypeVariable() {
    Class bClass = B.class;
    Method[] declaredMethods = bClass.getDeclaredMethods();
    for (Method declaredMethod : declaredMethods) {
        Type[] genericParameterTypes = declaredMethod.getGenericParameterTypes();
        System.out.println(Arrays.toString(genericParameterTypes));
    }
    System.out.println("--------------------------------------------");
    Field[] declaredFields = bClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        Type genericType = declaredField.getGenericType();
        System.out.println(declaredField.getName() + " : " + (genericType instanceof TypeVariable));
    }
}
[E]
--------------------------------------------
list : false
map : false
e : true
方法 getBounds()

返回表示此类型变量上限的Type对象数组。 请注意,如果没有明确声明上限,则上限为Object。

@Test
public void getBounds(){
    TypeVariable>[] typeParameters = B.class.getTypeParameters();
    for (TypeVariable> typeParameter : typeParameters) {
        System.out.println(typeParameter.getName());
        Type[] bounds = typeParameter.getBounds();
        System.out.println("bounds:"+Arrays.toString(bounds));
    }
}
T
bounds:[class java.lang.String]
E
bounds:[class java.lang.Object]
getGenericDeclaration()

返回声明此类型变量的GenericDeclaration对象
关于GenericDeclaration

@Test
public void getGenericDeclaration(){
    TypeVariable[] typeParameters = B.class.getTypeParameters();
    for (TypeVariable typeParameter : typeParameters) {
        System.out.println(typeParameter.getName());
        GenericDeclaration genericDeclaration = typeParameter.getGenericDeclaration();
        System.out.println(genericDeclaration);
    }
}
T
class com.example.myapplication.type.TestTypeVariable$B
E
class com.example.myapplication.type.TestTypeVariable$B
getName()

返回此类型变量的名称

@Test
public void getName(){
    TypeVariable[] typeParameters = B.class.getTypeParameters();
    for (TypeVariable typeParameter : typeParameters) {
        String name = typeParameter.getName();
        System.out.println(typeParameter.getName()+" getName:"+name);
    }
}
T getName:T
E getName:E
WildcardType

通配符的类型。例如? , ? extends Number ?和extends Number ,? super Integer 和?
super Integer 。

public class A {
    List ts;//属于WildcardType
    List list;//属于WildcardType
    List ins;//属于WildcardType
}
@Test
public void wildcardTypeInClass() {
    Class aClass = A.class;
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        ParameterizedType genericType = (ParameterizedType) declaredField.getGenericType();
        for (Type type1 : genericType.getActualTypeArguments()) {
            System.out.println("----------------------------------");
            System.out.println("getTypeName():  " + type1.getTypeName());
            System.out.println("is WildcardType: "+ (type1 instanceof WildcardType));
        }
    }
}
getTypeName():  ? extends java.lang.String
is WildcardType: true
----------------------------------
getTypeName():  ?
is WildcardType: true
----------------------------------
getTypeName():  ? super java.lang.Integer
is WildcardType: true
方法

WildcardType定义了两个方法

Type[] getUpperBounds();
获取类型的上边界,使用extends关键字时,传递的类型必须是指定类型的子类,指定类型即上边界,使用任何超出上边界的类型都是错误的

Type[] getLowerBounds();
获取类型的下边界,使用super关键字时,传递的类型必须是指定类型的父类,指定类型即下边界,使用任何超出下边界的类型都是错误的

@Test
public void testMethods(){
    Class aClass = A.class;
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        ParameterizedType genericType = (ParameterizedType) declaredField.getGenericType();
        for (Type type1 : genericType.getActualTypeArguments()) {
            System.out.println("getTypeName():  " + type1.getTypeName());
            if (type1 instanceof WildcardType) {
                System.out.println("getUpperBounds(): " + Arrays.toString(((WildcardType) type1).getUpperBounds()));
                System.out.println("getLowerBounds(): " + Arrays.toString(((WildcardType) type1).getLowerBounds()));
                System.out.println("----------------------------------");
            }
        }
    }
}
getTypeName():  ? extends java.lang.String
getUpperBounds(): [class java.lang.String]
getLowerBounds(): []
----------------------------------
getTypeName():  ?
getUpperBounds(): [class java.lang.Obj	ect]
getLowerBounds(): []
----------------------------------
getTypeName():  ? super java.lang.Integer
getUpperBounds(): [class java.lang.Object]
getLowerBounds(): [class java.lang.Integer]
----------------------------------

参考资料:
java Type 详解
Java中rtti的实现–>Type类介绍

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号