Java学习之反射机制及应用场景介绍
程序员文章站
2024-03-12 09:47:50
前言:
最近公司正在进行业务组件化进程,其中的路由实现用到了java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的eventbus 2.x版本还是re...
前言:
最近公司正在进行业务组件化进程,其中的路由实现用到了java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的eventbus 2.x版本还是retrofit、早期的view注解框架都或多或少的用到java的反射机制。
什么是java反射机制?
java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的方法的功能称为java的反射机制。
反射机制提供了哪些功能?
- 在运行时判定任意一个对象所属的类
- 在运行时构造任意一个类的对象;
- 在运行时判定任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法;
- 生成动态代理;
java反射机制类:
java.lang.class; //类 java.lang.reflect.constructor;//构造方法 java.lang.reflect.field; //类的成员变量 java.lang.reflect.method;//类的方法 java.lang.reflect.modifier;//访问权限
java反射机制实现:
1.)class对象的获取
//第一种方式 通过对象getclass方法 person person = new person(); class<?> class1 = person.getclass(); //第二种方式 通过类的class属性 class1 = person.class; try { //第三种方式 通过class类的静态方法——forname()来实现 class1 = class.forname("com.whoislcj.reflectdemo.person"); } catch (classnotfoundexception e) { e.printstacktrace(); }
2.)获取class对象的摘要信息
boolean isprimitive = class1.isprimitive();//判断是否是基础类型 boolean isarray = class1.isarray();//判断是否是集合类 boolean isannotation = class1.isannotation();//判断是否是注解类 boolean isinterface = class1.isinterface();//判断是否是接口类 boolean isenum = class1.isenum();//判断是否是枚举类 boolean isanonymousclass = class1.isanonymousclass();//判断是否是匿名内部类 boolean isannotationpresent = class1.isannotationpresent(deprecated.class);//判断是否被某个注解类修饰 string classname = class1.getname();//获取class名字 包含包名路径 package apackage = class1.getpackage();//获取class的包信息 string simplename = class1.getsimplename();//获取class类名 int modifiers = class1.getmodifiers();//获取class访问权限 class<?>[] declaredclasses = class1.getdeclaredclasses();//内部类 class<?> declaringclass = class1.getdeclaringclass();//外部类
3.)获取class对象的属性、方法、构造函数等
field[] allfields = class1.getdeclaredfields();//获取class对象的所有属性 field[] publicfields = class1.getfields();//获取class对象的public属性 try { field agefield = class1.getdeclaredfield("age");//获取class指定属性 field desfield = class1.getfield("des");//获取class指定的public属性 } catch (nosuchfieldexception e) { e.printstacktrace(); } method[] methods = class1.getdeclaredmethods();//获取class对象的所有声明方法 method[] allmethods = class1.getmethods();//获取class对象的所有方法 包括父类的方法 class parentclass = class1.getsuperclass();//获取class对象的父类 class<?>[] interfaceclasses = class1.getinterfaces();//获取class对象的所有接口 constructor<?>[] allconstructors = class1.getdeclaredconstructors();//获取class对象的所有声明构造函数 constructor<?>[] publicconstructors = class1.getconstructors();//获取class对象public构造函数 try { constructor<?> constructor = class1.getdeclaredconstructor(new class[]{string.class});//获取指定声明构造函数 constructor publicconstructor = class1.getconstructor(new class[]{});//获取指定声明的public构造函数 } catch (nosuchmethodexception e) { e.printstacktrace(); } annotation[] annotations = class1.getannotations();//获取class对象的所有注解 annotation annotation = class1.getannotation(deprecated.class);//获取class对象指定注解 type genericsuperclass = class1.getgenericsuperclass();//获取class对象的直接超类的 type type[] interfacetypes = class1.getgenericinterfaces();//获取class对象的所有接口的type集合
4.)class对象动态生成
//第一种方式 class对象调用newinstance()方法生成 object obj = class1.newinstance(); //第二种方式 对象获得对应的constructor对象,再通过该constructor对象的newinstance()方法生成 constructor<?> constructor = class1.getdeclaredconstructor(new class[]{string.class});//获取指定声明构造函数 obj = constructor.newinstance(new object[]{"lcj"});
5.)动态调用函数
try { // 生成新的对象:用newinstance()方法 object obj = class1.newinstance(); //判断该对象是否是person的子类 boolean isinstanceof = obj instanceof person; //首先需要获得与该方法对应的method对象 method method = class1.getdeclaredmethod("setage", new class[]{int.class}); //调用指定的函数并传递参数 method.invoke(obj, 28); method = class1.getdeclaredmethod("getage"); object result = method.invoke(obj, new class[]{}); } catch (instantiationexception e) { e.printstacktrace(); } catch (illegalaccessexception e) { e.printstacktrace(); } catch (nosuchmethodexception e) { e.printstacktrace(); } catch (invocationtargetexception e) { e.printstacktrace(); }
6.)通过反射机制获取泛型类型
例如下面这种结构
//people类 public class people<t> {} //person类继承people类 public class person<t> extends people<string> implements personinterface<integer> {} //personinterface接口 public interface personinterface<t> {}
获取泛型类型
person<string> person = new person<>(); //第一种方式 通过对象getclass方法 class<?> class1 = person.getclass(); type genericsuperclass = class1.getgenericsuperclass();//获取class对象的直接超类的 type type[] interfacetypes = class1.getgenericinterfaces();//获取class对象的所有接口的type集合 getcomponenttype(genericsuperclass); getcomponenttype(interfacetypes[0]);
getcomponenttype具体实现
private class<?> getcomponenttype(type type) { class<?> componenttype = null; if (type instanceof parameterizedtype) { //getactualtypearguments()返回表示此类型实际类型参数的 type 对象的数组。 type[] actualtypearguments = ((parameterizedtype) type).getactualtypearguments(); if (actualtypearguments != null && actualtypearguments.length > 0) { componenttype = (class<?>) actualtypearguments[0]; } } else if (type instanceof genericarraytype) { // 表示一种元素类型是参数化类型或者类型变量的数组类型 componenttype = (class<?>) ((genericarraytype) type).getgenericcomponenttype(); } else { componenttype = (class<?>) type; } return componenttype; }
6.)通过反射机制获取注解信息
这里重点以获取method的注解信息为例
try { //首先需要获得与该方法对应的method对象 method method = class1.getdeclaredmethod("jumptogoodsdetail", new class[]{string.class, string.class}); annotation[] annotations1 = method.getannotations();//获取所有的方法注解信息 annotation annotation1 = method.getannotation(routeruri.class);//获取指定的注解信息 typevariable[] typevariables1 = method.gettypeparameters(); annotation[][] parameterannotationsarray = method.getparameterannotations();//拿到所有参数注解信息 class<?>[] parametertypes = method.getparametertypes();//获取所有参数class类型 type[] genericparametertypes = method.getgenericparametertypes();//获取所有参数的type类型 class<?> returntype = method.getreturntype();//获取方法的返回类型 int modifiers = method.getmodifiers();//获取方法的访问权限 } catch (nosuchmethodexception e) { e.printstacktrace(); }
反射机制的应用场景:
- 逆向代码 ,例如反编译
- 与注解相结合的框架 例如retrofit
- 单纯的反射机制应用框架 例如eventbus 2.x
- 动态生成类框架 例如gson
反射机制的优缺点:
优点:运行期类型的判断,动态类加载,动态代理使用反射。
缺点: 性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。
总结:
java的反射机制在平时的业务开发过程中很少使用到,但是在一些基础框架的搭建上应用非常广泛,今天简单的总结学习了一下,还有很多未知的知识等以后用到再做补充。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。