java反射field相关知识

Class c = ArrayList.class;

c.isPrimitive(); //判断c是否为基本数据类型

c.isAssignableFrom(List.class); //判断c是否是List类的子类或父类

c.getGenericType(); //得到泛型类型

一、判断指定class是否基础类型或者包装类型

方法一

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.9</version>
</dependency>

ObjectUtil.isBasicType 判断是否为基本类型,包括包装类型和原始类型。

包装类型:

  • Boolean
  • Byte
  • Character
  • Double
  • Float
  • Integer
  • Long
  • Short

原始类型:

  • boolean
  • byte
  • char
  • double
  • float
  • int
  • long
  • short
boolean basicType = ObjectUtil.isBasicType(a);

二、普通类型的变量直接field.getType()即可以获取到他们的类型

Class type = field.getType();

assertEquals(type,String.class);

三、数组类型

数组类型不像其他的类型可以通过isAssignableFrom()函数来进行判断,他需要使用isArray() 来判断该type是否是一个数组类型,然后使用getComponentType() 获取他的元素的类型

Class> type = field.getType();
//一般来说,判断是否是某种类型是可以使用isAssignableFrom
// 判断是否是数组类型比较特殊,要使用isArray()这个函数
if (type.isArray()){
  //获得数组的类型,使用getComponentType()这个方法
  Class componentType = type.getComponentType();

  assertEquals(componentType,Integer.class);
}

四、带泛型的类型

带泛型的类型就是类似于List这样的类型,我们现在的任务就是获取到String这个类型。

ParameterizedType表示参数化的类型,例如Collection这样的类型。我们可以通过getGenericType()方法获得该子类,当你的类型带有参数的时候就会返回ParameterizedType,否则会返回普通的类型(class)

Class<T> tc = T.class;

Field[] fields = tc.getDeclaredFields();
for (Field f : fields) {
  Class fc = f.getType();
  //判空
  if (fc == null){
    continue;
  }
  if(fc.isPrimitive()){
    System.out.println("基本数据类型: " + f.getName() + "  " + fc.getName());
  }else{
    if(fc.isAssignableFrom(List.class)){ //判断是否为List
      System.out.println("List类型:" + f.getName());
      //如果是List类型,得到其Generic的类型
      Type gt = f.getGenericType();
      //判断是否泛型类型,例:List list = new ArrayList();这种会为false
      if(gt instanceof ParameterizedType){
        ParameterizedType pt = (ParameterizedType)gt;
        Class lll = (Class)pt.getActualTypeArguments()[0];
        System.out.println("\t\t" + lll.getName());
      }
    }
  }
}

五、复杂嵌套

如果我们有一个嵌套List,我们想拿到嵌套在最里面的类型,那么我们可以这么做呢?

//其实我们可以使用递归的思想去获得最里面的类型
Field field = Some.class.getDeclaredField("matrix");
assertEquals(getBaseType(field.getGenericType()),Double.class);


public static Type getBaseType(Type genericReturnType){
  Objects.requireNonNull(genericReturnType);
  //如果出入的type是ParameterizedType并且是List类型则进入递归便利
  //第二个是将传入的类型转换为ParameterizedType类型,然后getRawType即自己的类型,强转为class类型后进行对比
  if (genericReturnType instanceof ParameterizedType &&
    List.class.isAssignableFrom((Class)(((ParameterizedType) genericReturnType).getRawType()))){
    Type[] actualTypeArguments = ((ParameterizedType)genericReturnType).getActualTypeArguments();
    Type type = actualTypeArguments[0];
    return getBaseType(type);
  }else{
  	return genericReturnType;
  }
}

六、多个泛型参数

Field field = Some.class.getDeclaredField("map");
Type type = field.getGenericType();
if (type instanceof ParameterizedType){
  ParameterizedType parameterizedType = (ParameterizedType)type;
  Type[] actualTypes = parameterizedType.getActualTypeArguments();
  assertEquals(actualTypes[0],String.class);
  assertEquals(actualTypes[1],Class.class);
}else{
	throw new IllegalStateException();
}

站在巨人肩膀上摘苹果

https://blog.csdn.net/weixin_39590601/article/details/114359916

https://blog.csdn.net/weixin_43831204/article/details/107670994

posted @ 2023-01-10 11:15  未月廿三  阅读(311)  评论(0编辑  收藏  举报