需求:需要通过反射动态获取类的字段类型,然后做特殊处理

Java反射getDeclaredField和getField的区别

getDeclaredFiled 只能获取类本身的属性成员(包括私有、共有、保护)

getField 仅能获取类(及其父类可以自己测试) public属性成员

反射获取所有的字段

Class clazz = 类.class;
Field[] fields= classzz.getDeclaredFields();

获得某个具体字段,并获取类型

String fieldType=clazz.getDeclaredField("需要获取的字段").getType().toString();
if(fieldType.contains("Integer")||fieldType.contains("Long")){
//这里做业务处理
}

下面再看一个完整的例子:

public class User {public String name;public int age;public String address;
}
public static void getFieldsValue(Object obj) {Field[] fields = obj.getClass().getDeclaredFields();/*** 基本类型、包装类型、String类型*/String[] types = {"java.lang.Integer","java.lang.Double","java.lang.Float","java.lang.Long","java.lang.Short","java.lang.Byte","java.lang.Boolean","java.lang.Character","java.lang.String","int","double","long","short","byte","boolean","char","float"};for(Field f : fields){f.setAccessible(true);try {for(String str : types) {if(f.getType().getName().equals(str))System.out.println("字段:"+f.getName()+" 类型:"+f.getType().getName()+" 值:"+ f.get(obj));}} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}

获取更多类型方法:

Java-使用反射获取类型信息:https://blog.csdn.net/alisonyu/article/details/82762765

数组类型

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

public void queryArrayType() throws NoSuchFieldException {Field field = Some.class.getDeclaredField("具体字段");Class<?> type = field.getType();//一般来说,判断是否是某种类型是可以使用isAssignableFrom// 判断是否是数组类型比较特殊,要使用isArray()这个函数if (type.isArray()){//获得数组的类型,使用getComponentType()这个方法Class<?> componentType = type.getComponentType();assertEquals(componentType,Integer.class);}else{throw new IllegalStateException();}
}

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

public void getListType() throws NoSuchFieldException {Field field = Some.class.getDeclaredField("list");//如果类似于List<String>这样的类型就是一种GenericType//注意这是一种Type类型Type type = field.getGenericType();if (type instanceof ParameterizedType){//泛型参数类型ParameterizedType parameterizedType = (ParameterizedType)type;Type[] actualTypes = parameterizedType.getActualTypeArguments();//因为List<String>获得第一个泛型参数,因为只有一个,我们取第一个//如果我们有多个泛型参数,我们可以根据顺序取不同的泛型参数assertEquals(actualTypes[0],String.class);//如果获得List这个原始类型呢?assertEquals(parameterizedType.getRawType(),List.class);}else{throw new IllegalStateException();}
}

下面是我以前写的关于反射的笔记,如果有对反射基础知识不清楚的需要补课:

说明:

Class这个Java类保存的是一个Java类的meta信息(元信息)。一般在反射中使用。 
Object类,是所有Java类的根。包括Class类。

Class类:用于描述一切类/接口.枚举是一种类,注解是一种接口

Class实例:就是指JVM中一份字节码

Class类:用于描述一切类/接口.问题:那Class实例到底表示的是哪一份字节码,为了明确区分出Class实例表示的是谁的字节码.Class类提供了泛型

Class<Date>  clz1 = Date.class;//clz1表示是Date的字节码

Class<String>  clz2 = String.class;//clz2表示的是String的字节码

如何得到Class的实例:
     1.类名.class(就是一份字节码)
     2.Class.forName(String className);根据一个类的全限定名来构建Class对象
     3.每一个对象多有getClass()方法:obj.getClass();返回对象的真实类型

一个类在JVM中只有一份字节码;

第一种方式:数据类型.class
  Class<User> clz1 = User.class;

第二种方式: Class.forName(String className);
Class<?>  clz2 = Class.forName("cn.itcast.cd.User");
使用?是因为此时Class不知道类,因为传的是字符串


反射很强大,但是耗性能.主要是为了做工具和框架使用的.

第三种方式:  对象.getClass();得到对象的真实类型,每个方法都有所以在Object里

User u  = new User();
   Class clz3 = u.getClass();

clz1 == clz2 == clz3:因为表示都是JVM中共同的一份字节码(User.class)

new一个类才会把字节码从IO加载到内存。

Java内置9大的Class实例

对于对象来说,可以直接使用对象.getClass()或者Class.forName(className); 类名.class都可以获取Class实例.

但是我们的基本数据类型,就没有类的权限定名,也没有getClass方法.
问题:那么如何使用Class类来表示基本数据类型的Class实例?
byte,short,int,long,char,float,double,boolean ,void关键字
上述8种类型和void关键字,都有class属性.
表示int的Class对象:  Class clz = int.class;
表示boolean的Class对象:  boolean.class;
void:  Class clz = void.class;

所有的数据类型都有class属性,表示都是Class对象.

思考:
int的包装类是Integer
Integer.class     ==?==         int.class
结果是false,说明是两份字节码.

Integer 和int是同一种数据类型吗? 不是

但是在八大基本数据类型的包装类中都有一个常量:TYPE
TYPE表示的是该包装类对应的基本数据类型的Class实例.
如:Integer.TYPE----->int.class
   Integer.TYPE==int.class;//YES
   Integer.TYPE == Integer.class;//ERROR

数组的Class实例:
String[] sArr1 = {"A","C"};
String[] sArr2 = {};
String[][] sArr = {};

int[] sArr = {};

表示数组的Class实例:
   String[] sArr1 = {"A","C"};
   Class clz = String[].class;//此时clz表示就是一个String类型的一位数组类型

所有具有相同元素类型和维数的数组才共享同一份字节码(Class对象);
   注意:和数组中的元素没有一点关系.

获取类中的构造器

获取某一个类中的所有的构造器:
   1,明确操作的是哪一份字节码对象
   2,获取构造器

Class类获取构造器方法:
Constructor类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器

public Constructor<?>[] getConstructors():该方法只能获取当前Class所表示类的public修饰的构造器

public Constructor<?>[] getDeclaredConstructors():获取当前Class所表示类的所有的构造器,和访问权限无关

public Constructor<T> getConstructor(Class<?>... parameterTypes) :获取当前Class所表示类中指定的一个public的构造器
      参数:parameterTypes表示:构造器参数的Class类型
      如:public User(String name)
        Constructor c =  clz.getConstructor(String.class);

public class User {public User(){};public User(String name){};public User(String name,String school){};
}
       System.out.println(Integer.TYPE);Class<User> clz=User.class;Constructor[]cs=clz.getConstructors();for (Constructor c : cs) {System.out.println(c);}//获取单个构造器Constructor c=clz.getDeclaredConstructor(String.class);System.out.println(c);

调用构造器,创建对象

Constructor<T>类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器

常用方法:
public T newInstance(Object... initargs):如调用带参数的构造器,只能使用该方式.
     参数:initargs:表示调用构造器的实际参数
     返回:返回创建的实例,T表示Class所表示类的类型

如果:一个类中的构造器可以直接访问,同时没有参数.,那么可以直接使用Class类中的newInstance方法创建对象.
 public Object newInstance():相当于new 类名();

修改User

public class User {public User() {System.out.println("---");}public User(String name) {System.out.println(name);}public User(String name, String school) {System.out.println(name + " " + school);}
}
public static void main(String[] args) throws Exception {        System.out.println(Integer.TYPE);Class<User> clz=User.class;Constructor[]cs=clz.getConstructors();for (Constructor c : cs) {System.out.println(c);}//获取单个构造器//泛型Constructor<User> c=clz.getDeclaredConstructor(String.class);System.out.println(c);      User u=c.newInstance("abc");//不带泛型Constructor c2=clz.getDeclaredConstructor(String.class);System.out.println(c2);       Object u2=c2.newInstance("abc");        }

Class.forName方式

如果访问不带参数的构造器可以直接用Class的newInstance()方法

修改访问权限为private

public class User {public User() {System.out.println("---");}private User(String name) {System.out.println(name);}public User(String name, String school) {System.out.println(name + " " + school);}
}

报错

Constructor<User> c=clz.getDeclaredConstructor(String.class);System.out.println(c);c.setAccessible(true);User u=c.newInstance("abc");

获取类中的方法

使用反射获取某一个类中的方法:
1.找到获取方法所在类的字节码对象
2.找到需要被获取的方法

Class类中常用方法:
public Method[] getMethods():获取包括自身和继承过来的所有的public方法

public Method[] getDeclaredMethods():获取自身所有的方法(不包括继承的,和访问权限无关)

public Method getMethod(String methodName,

Class<?>... parameterTypes):表示调用指定的一个公共的方法(包括继承的)
       参数:
               methodName: 表示被调用方法的名字
               parameterTypes:表示被调用方法的参数的Class类型如String.class

public Method getDeclaredMethod(String name,

Class<?>... parameterTypes):表示调用指定的一个本类中的方法(不包括继承的)
        参数:
               methodName: 表示被调用方法的名字
               parameterTypes:表示被调用方法的参数的Class类型如String.class

public class User {public User() {System.out.println("---");}public User(String name) {System.out.println(name);}public User(String name, String school) {System.out.println(name + " " + school);}public void Say(String name) {System.out.println(name);}public void Say(String name, String school) {System.out.println(name + " " + school);}
}
Class clz=User.class;Method[] m=clz.getMethods();for (Method c : m) {System.out.println(c);}System.out.println("----------------------");m=clz.getDeclaredMethods();for (Method c : m) {System.out.println(c);}

Method m1=clz.getMethod("Say", String.class);System.out.println(m1);Method m2=clz.getMethod("Say", String.class,String.class);System.out.println(m2);

Java反射以及应用相关推荐

  1. Java 反射 (快速了解反射)

    反射的概念 JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java ...

  2. java反射最佳实践,java反射性能测试分析

    java反射性能测试分析 java有别于其他编程语言而让我着迷的特性有很多,其中最喜欢的是接口设计,他让我们设计的东西具有美感.同样反射也是我比较喜欢的一个特性,他让程序自动运行,动态加载成为了可能, ...

  3. java 获取 反射 方法 名_乐字节Java反射之一:反射概念与获取反射源头Class

    一.Java反射机制概念 "程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言",如Python, Ruby是动态语言:显然C++,Java,C#不是动态语言,但是JAV ...

  4. java反射用在哪里_Java反射

    昨天去参加比赛了,所以没有进行博客迁移.人生中的第一场健体比赛,虽然没得奖,但是收获和带来的思考颇丰.意外地进入了男子B组(174以上)的半决赛,然后在半决赛的时候还被裁判员点名出去单独比较,这个很让 ...

  5. Java反射(详述版)

    一.什么是反射? 我们先来看一个例子: package venus; public class Student {public String name;public Student(){System. ...

  6. java 反射 动态代理

    在上一篇文章中介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大 ...

  7. Java反射 - 私有字段和方法

    尽管普遍认为通过Java Reflection可以访问其他类的私有字段和方法. 这并不困难. 这在单元测试中可以非常方便. 本文将告诉你如何. 访问私有字段 要访问私有字段,您需要调用Class.ge ...

  8. 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

    作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...

  9. Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法...

    Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法 www.MyException.Cn   发布于:2012-09-15 ...

最新文章

  1. MIT长篇论文:我们热捧的AI翻译和自动驾驶,需用技术性价比重估
  2. vrrp虚拟路由冗余协议简图
  3. 华为服务器MLC硬盘ID号,RH2288H RH5885H V3 3.5寸 SAS SATA华为服务器硬盘架子 支架
  4. java从Object类型转换成double类型
  5. 视频直播/远程会议中的AI关键技术探索应用
  6. MinGw+Msys搭建环境 编译ffmpeg
  7. Bootstrap按钮组中按钮的尺寸
  8. 【论文写作】体育城场地预约系统的数据表如何设计
  9. 多元梯度下降法(2)--学习率α machine learning
  10. 四川大学计算机学院保研规定,2020四川大学计算机学院保研夏令营通知
  11. VUE和Element-UI下拉框select实现拼音,中文搜索
  12. 今天申请了亚马逊新加坡站点
  13. 高德地图测开笔试题分享
  14. UVA - 10158 War
  15. 企业劳务派遣的人员怎么界定身份
  16. 中科大计算机考研录取分数线_计算机专业学校考研难度排行榜 计算机考研难度排名...
  17. docker看远程仓库镜像_Docker 镜像使用
  18. 基因序列的保守性分值
  19. 一个简单有趣的小问题,枫叶嵌套问题的完美解决
  20. python的post请求中加参数_Python 模拟post请求

热门文章

  1. python嵩天课堂笔记_[Python机器学习]强化学习笔记(嵩天礼欣老师mooc第三周)
  2. 看网友如何定义C++
  3. C++:名字空间的使用
  4. 力扣(LeetCode)刷题,简单题(第24期)
  5. Qt开发环境的下载地址
  6. 深度学习--TensorFlow(4)BP神经网络(损失函数、梯度下降、常用激活函数、梯度消失梯度爆炸)
  7. 使用python爬取视频
  8. windows下opencv安装及配置(vs2010环境)
  9. activemq 开启监听_ActiveMQ 消息监听 MessageListener 的使用
  10. error C2733: 不允许重载函数的第二个 C 链接