Java 反射机制

Posted Nothing Is Given.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 反射机制相关的知识,希望对你有一定的参考价值。

  一、反射(Reflection)

  1、反射的概念

  反射是程序可以访问、检测和修改它本身状态或者行为的能力。通过反射,可以动态获取对象信息以及动态调用对象的方法。

  反射的基础是因为在运行状态中,JVM能够知道对象的所有属性和方法,并且能够调用它的任意一个方法或访问其任一属性。

  反射机制使得程序可以在运行时动态加载、查看和使用编译期间完全未知的类(对象)。

 

  2、反射机制提供的功能 

  • 运行时检测对象的类型;
  • 动态创建对象;
  • 减速对象的属性和方法;
  • 调用对象的任意方法;
  • 修改构造器、方法和属性的可见性;
  • 动态生成代理。

 

  3、反射的通常用途

  • 用于程序检查工具和调试器,它能获取程序在运行时刻的内部结构;
  • 在运行时刻与注解配合,动态改变对象的行为,例如,为特定对象添加日志、权限控制等操作。

 

  二、反射的实现

  1、反射机制的实现基于4个类,也可以把他们看成一个类的各个部分。

  Class:代表运行时对象的类型信息,JVM使用这些类型信息确定方法。

  Constructor:表示类的构造器,即构造方法的描述类。

  Field:用来描述对象的属性集合。

  Method:用来描述方法。

  值得注意的是,通过上面方法访问反射机制创建的对象的私有构造器、属性、方法(少见)时,要先通过setAccessible(boolean T_or_F)方法修改访问权限!

 

  2、Class类——反射的基石

  Class类的对象用来描述运行时的类和接口,也用来表达enum、数组、基本数据类型以及关键词void。当一个类被加载或者当类加载器的defineClass()方法被调用,JVM就会自动产生一个Class对象。

  要查看任何类,都必须获得一个Class对象。然后由Class对象调用反射APIs。

  怎么获得Class对象?两种方式:

public class role{}
/*第一种*/
Class cls=Role.class;
/*第二种,forName()方法的参数必须是完整的路径类名(包名+类名),并且该方法需要捕获ClassNotFoundException异常。*/
Class cls=Class.forName(“cn.edu.ldu.javacourse.ch7.Role”);

   在得到Class的实例对象后就可以创建Role类的实例了,newInstance()调用类的默认构造器生成对象:

/*newInstance()方法的缺点是只能调用默认构造函数*/
Object o=cls.newInstance();

  Class的其他方法可以获取到类的构造方法、属性和成员方法:

  • getConstructor();
  • getField();
  • getMethod();

         同时这三个方法还有相应的getDeclaredxxx()版本,只获取该类自己声明的成员而不是从父类继承。

 

  3、Constructor类——获取构造器

  Constructor类是构造方法的描述类,Constructors对象可以通过Class对象的4个getXXX()方法获得(也可以获得构造器数组):

/*Class类有4个方法获得Constructors对象*/ 
Constructors con=cls.getXXXX();

/*然后设置所获得的构造器的访问权限*/
con. setAccessible(true);

/*通过con的newInstance()方法创建新的对象*/
Object obj=con.newInstance (new Object[]{“Jerry”});

/*若要使用私有构造器,记得修改访问权限*/ 

  

  4、Field类——获取成员变量

  成员变量用Field类进行封装,使用与上面相似。

/*返回了方法名*/
Field mem=cls.getDeclaredField("fieldName");
mem.setAccessible(true);
System.out.println("we get fields:"+mem.get(obj));

/*访问私有变量也要改变访问权限*/

 

  5、Method类——获取方法

   Method类封装方法,基于反射获取并执行方法:

Method me=cls.getMethod("methodBame",null);
Object name=me.invoke(obj,null);

 

  6、数组

  数组与所有对象一样,都通过Class的对象描述,也可使用标准getClass()方法获得数组的Class对象。

  但是数组不是类,没有构造函数也没有可访问的属性和方法。即反射为普通类提供的访问函数不能用于数组。

  反射处理数组使用java.lang.reflect.Array类提供的静态方法,可以创建新的数组,可以获得数组对象的长度,以及读、写数组对象的索引值。

  反射机制创建数组:

/*第一个参数int.class指定数组类型,第二个参数声明数组中元素的个数。*/
int[] intArray=(int[]) Array.newInstance( int.class, 3);

/*访问通过反射创建的数组*/
/*intArray参数是一个具体的数组*/
Array.get (intArray,0);
Array.set (intArray,index,value); 

   思考,怎么重新调整现有数组大小?

 

以上是关于Java 反射机制的主要内容,如果未能解决你的问题,请参考以下文章

反射机制入门

反射机制入门

java 反射代码片段

深入理解java的反射机制

Java反射机制

Java核心技术梳理-类加载机制与反射