Java反射以及应用
需求:需要通过反射动态获取类的字段类型,然后做特殊处理
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);
相关文章:

【MATLAB】雅可比矩阵jacobi matrix
参考页面: https://baike.baidu.com/item/%E9%9B%85%E5%8F%AF%E6%AF%94%E7%9F%A9%E9%98%B5/10753754?fraladdin#1 在向量微积分中,雅可比矩阵是一阶偏导数以一定方式排列成的矩阵,其行列式称为雅可比行列式。 由球坐标系到直角坐标系的转…

Laravel:使用Migrations
1、首先利用artisan创建一个可迁移的数据表模板,该命令运行后会在database/migrations目录下生成一个文件 php artisan make:migration create_fees_count_table --createfees_count 2、生成的文件包含up和down两个方法,其中up中是包含了添加表ÿ…

基于libevent和unix domain socket的本地server
https://www.pacificsimplicity.ca/blog/libevent-echo-server-tutorial 根据这一篇写一个最简单的demo。然后开始写client。 client调优 client最初的代码如下: 1 #include <sys/socket.h>2 #include <sys/un.h>3 #include <stdio.h>4 #include …

软件体系架构模式之一什么是软件架构模式
什么是软件架构模式 计划启动未开发的软件项目?然后选择正确的架构模式将对项目的结果起关键作用。选择市场上最流行或最新的技术并不总是意味着会带来最好的结果。但是,选择最合适的解决方案将为行之有效的问题和反复出现的问题提供可靠的解决方案。 …

HP 服务器 iLO 远程控制软件 介绍
iLO了解:iLO 是一组芯片,内部是vxworks的嵌入操作系统,在服务器的背后有一个标准RJ45口对外连接生产用交换机或者带外管理的交换机。iLO 全名是 Integrated Lights-out,它是惠普某些型号的服务器上集成的远程管理端口,它能够允许用…
【MATLAB】数据分析之数据插值
插值:求过已知有限个数据点的近似函数。 区别于拟合: 拟合:已知有限个数据点求近似函数,不要求过已知数据点,只要求在某种意义下它在这些点上的总偏差最小。 基本常用的插值方法:拉格朗日多项式插值&…

迈斯!啊呸~数学
1.数论 快速幂 int po(int x,int y) {int ans1;while(y){if(y%21)ans1ll*ans*x%p;x1ll*x*x%p;y/2;}return ans; } 乘法逆元(保证模域p与求逆元的数互质) po(a,p-2);//a为需要求逆元的数 扩展欧几里得(exgcd) #include<cstdio&g…

软件体系架构模式之二分层体系结构
分层体系结构模式是n层模式,其中组件被组织在水平层中。这是设计大多数软件的传统方法,并且具有独立性。这意味着所有组件都是互连的,但彼此之间不依赖。 图1:分层架构 在此体系结构中有四层,其中每一层在模块和其中的…

linux下mysql的root密码忘记解决方法
1.首先确认服务器出于安全的状态,最安全的状态是到服务器的Console上面操作,并且拔掉网线,或者可以使用--skip-networking限制只能从本地连接2.修改MySQL的登录设置: # vim /etc/my.cnf在[mysqld]的段中加上…
【Python】turtle库的小应用
心血来潮,哈哈哈,画的不好,请多见谅 大家如果想要尝试turtle库,可以借鉴: https://www.cnblogs.com/nowgood/p/turtle.html 导入库,我的pycharm里可以直接使用,哈哈哈,不行就pip…

[转]MySQL修改时区的方法小结
本文转自:https://www.cnblogs.com/mracale/p/6064447.html 这篇文章主要介绍了MySQL修改时区的方法,总结分析了三种常见的MySQL时区修改技巧,包括命令行模式、配置文件方式及代码方式,需要的朋友可以参考下 方法一:通过mysql命令行模式下动态修改 1.1 查…

swift轮播图代码
import UIKit private let CycleCellID "CycleCellID" class BannerCycleView: UIView { var layout : UICollectionViewFlowLayout! var collectionView :UICollectionView! var pageContol : UIPageControl? var cycleTimer : Timer? let timeInterval : TimeI…

软件体系架构模式之三微内核体系架构
当您的软件系统或产品包含许多与外部实体的集成点时,微内核体系结构模式将非常有用。最重要的是,您将无法准确判断出将来将哪些实体集成到您的系统中。可以将微内核架构模式识别为基于插件的模式。。也称为插件架构模式,它由两个主要组件组成…
【MATLAB】交互式绘图(ginput,gtext,zoom)
1、ginput指令: [x,y]ginput(n) %(其功能是用鼠标从二维图形中获取n个点的数据坐标) x-8*pi:pi/100:8*pi; y1sin(x); y24*sin(x/4); plot(x,y1,r-,x,y2,k-); legend(sin(x),4sin(x/4)); grid on; [x,y]ginput(8); %在下方命令窗…

【斗医】【18】Web应用开发20天
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://qingkechina.blog.51cto.com/5552198/1544928 本文通过获取首页内容来讲解Web页面拖拽获取当前页数据,功能类似在google查看图…

数据库和缓存一致性的问题
经常看到有人问怎么解决数据库和缓存一致性的问题,这个问题我觉得是不要去解决。 如果你不信你先看我列的几种情况 假设 数据库一开始和缓存都是1元。 用户更新数据库的同时双写缓存。 1.双写不删 写库充值10元>>>返回成功 ----- 时间间隔 <<<…
【MATLAB】数据分析之求函数的极限(limit)
在MATLAB中采用limit函数求某个具体函数的极限,其调用格式如下: limit(expr,x,a):当xa时,对函数expr求极限,返回值为函数极限。limit(expr):默认当x0时,对函数expr求极限,返回值为函…

Spring Boot集成Swagger导入YApi@无界编程
接口APi开发现状 现在开发接口都要在类似YApi上写文档,这样方便不同的团队之间协作,同步更新接口,提高效率。 但是如果接口很多,你一个个手工在YApi去录入无疑效率很低。 如果是使用Spring Boot集成Swagger可以直接导入YApi非常…
【MATLAB】数据分析之函数数值积分
一、数值积分问题的数学表达 称为积分节点,称为求积系数。右端公式称为左端定积分的某个数值积分。MATLAB支持三重以下的积分运算。分别为: 在计算积分时,要求积分区间是确定的。 二、一元函数的数值积分 1、quad函数:采用遍历的…

c++对象切片
什么事对象切片:c在将一个派生类转换为基类的过程中,派生类的一部分将被基类接收不到,只能留下基类大小的对象。传值调用的切片:#include<iostream> using namespace std; class Base { public: virtual void func1() { cou…

javascript数据结构与算法-队列
定义 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为…

Oracle学习笔记十三 触发器
2019独角兽企业重金招聘Python工程师标准>>> 简介 触发器是当特定事件出现时自动执行的存储过程,特定事件可以是执行更新的DML语句和DDL语句,触发器不能被显式调用。 触发器的功能: 1.自动生成数据 2.自定义复杂的安全权限 3.提供…

使用Notepad++比较文件的差异
有时候需要比较两个文件的差异部分,如果不在git里可以使用Notepad的插件。 在Notepad中安装Compare插件 打开NotePad,点击工具栏上的插件--Plugin Manager--Show Plugin Manager,选中Compare 然后安装。 比如下看两个线程堆栈的差异…
【MATLAB】将向量表示的多项式用字符串输出的通用函数示例
%创建一个名为pprintf的M文件 function s pprintf(p) %UNTITLED7 此处显示有关此函数的摘要 % 此处显示详细说明 if nargin>1error(Too much input arguments); end while(p(1)0)p1[]; end llength(p); if l0s0; elseif l1snum2str(p(1)); elseif l2s strcat(num2str(p(…

30秒或更短的时间内弄懂的有用CSS代码片段
今天无意间看到这个,真的很牛逼,记录下中文网: caibaojian.com/30-seconds-…转载于:https://juejin.im/post/5bf278a85188255e9b61a226
【MATLAB】数据分析之多项式及其函数
1、多项式的表达式和创建 MATLAB中使用一维向量来表示多项式。将多项式按照降幂次序存放在向量中。 多项式就可以用向量 [2 3 5 0 1]来表示。 2、多项式求根 >> p[1 2 1]p 1 2 1>> r roots(p)r -1-13、由根创建多项式 >> r [2;3]r 23>>…

SpringBoot自定义异常源码分析
SpringBoot自定义异常源码分析 在类上加ControllerAdvice注解,在方法上加ExceptionHandler注解,就可以在方法里处理相应的异常。 1.自定义异常处理类AdditionalExceptionHandler 挂RestControllerAdvice注解: ------------------ 2.自定义…

Android 应用性能优化-StrictMode(严格模式)
为什么80%的码农都做不了架构师?>>> UI线程如果被阻塞5秒的话,那么应用程序此时就会弹出ANR的对话框,ANR对应用程序来说是一个很严重的问题。 如何防止应用程序出现ANR,怎么分析查看导致ANR问题的原因? 我…

跨进程通信,到底用长连接还是短连接
一个完整的软件系统大多数情况下是由多个进程共同协作进行的,哪怕它们在同一台服务器上。所以,进程之间如何进行高效的通信至关重要。 单个应用程序单个数据库这套基础开发套餐我相信每个人都经历过,甚至在初期它们还有可能部署在同一台服务器…

Java的List和Json转换以及StringRedisTemplate往redis存泛型对象
List转Json List<User> user new ArrayList(); String str JSON.toJSONString(user); Json 转List方法一 List<User> user JSON.parseArray(json,User.class); 如果是泛型方法需要使用TypeReference Json 转List 方法二 String json "[{}]"; Li…