欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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的反射机制在平时的业务开发过程中很少使用到,但是在一些基础框架的搭建上应用非常广泛,今天简单的总结学习了一下,还有很多未知的知识等以后用到再做补充。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。