当前位置: 移动技术网 > IT编程>开发语言>Java > Java学习之反射机制及应用场景介绍

Java学习之反射机制及应用场景介绍

2019年07月22日  | 移动技术网IT编程  | 我要评论

前言:

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

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网