您的位置:首页 > 编程语言 > Java开发

JAVA反射机制

2016-05-26 22:39 405 查看
JAVA反射机制

一、Java反射机制的概念

•JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象方法 的功能称为java语言的反射机制

Java反射机制是Java的特性之一,反射机制是构建框架基础的所在 我们为什么将这种机制命名为“反射”机制呢?
官方解答:要让Java程序能够运行,那么就得让Java类被Java虚拟机加载,Java类如果不被Java虚拟机加载,则不能正常运行,而现在我们运行的所有程序,都是在编译时就已经加载了我们所需要的那个类,

package cn.happy.reflet.classinfo;

public class TestReflect {
//如何使用javaApi获取类的属性的步骤
public static void main(String[] args) {
ReflectDemo rd=new ReflectDemo();

}
}


在主程序中调用

每个类被加载后,系统就会为该类生成一个对应的Calss对象,通过该Class对象就可以访问到Java虚拟机中的这个类,Java程序中获得Class对象通常有如下三种方式:

1.调用某个对象的getClass()方法
PerSon p=new Person();
Class cla=p.getClass();
2.调用某个类的Class属性来获取该类对应的Class对象
Class cla=Person.Class;
注意:需要在编译时就知道该类的名字
3.使用Class类的forName()静态方法 该方法需要传入字符串参数,该字符串参数的值是某个类的全名(即类名前添加完整的包名)。
Class cla=Class.forName("类的全路径名");



后两种方式都是直接根据类来取得该类的Class对象,相比之下,调用某个类的Class属性来获取该类对应的Class对象这种方式有如下两种优势:
1.代码更安全。程序在编译阶段就可以检查需要访问的Class对象是否存在
2.程序性能更高,因为这种方式无须调用方法。所以程序的性能更好

获取Class对象的方式

在获得了某个类所对应的Class对象之后,程序就可以调用Class对象的方法来获得该类的真实信息了,Class类提供了大量实例方法来获取Class对象所对应的类的详细信息
如何从Class类中获取信息
1.访问Class对应的类所包含的构造方法
//方法1
Constructor getConstructor(Class[] params)
返回此Class对象所表示的类的指定的public构造方法,params参数是按声明顺序标识该方法参数类型的Class对象的一个数组
构造方法的参数类型与params所指定的参数类型所匹配
示例:
Constructor co=c.getConstructor(String.Class,List.Class); (c为某Class对象)
//方法2
Constructor[] getConstructors();
返回此Class对象所表示的类的所有public 构造方法
//方法3
Constructor getDeclaredConstructor(Class[] patams);
返回此Class对象所表示的类的指定构造方法,与构造方法的访问级别无关

//方法4
Constructor[] getDeclaredConstructors();
返回此Class对象所表示的类的全部方法,与方法的访问级别无关

2.访问Class对应的类所包含的构造方法
//方法1
Method getMethod(String name,Class[] params);
返回此Class对象所表示的类的指定的public方法,name参数用于指定方法名称,params参数是按声明顺序表示该方法参数类型的Class对象的一个数组

//方法2.
Method[] getMethods();
返回此Class对象所表示的类的所有public方法

//方法3
Method getDeclaredMethod(String name.Class[] params);
返回此Class对象所表示的类的指定的方法。与方法的访问级别无关

//方法4
Method[] getDeclaredMethods();
返回此Class对象所表示的类所有的方法。与方法的访问级别无关

访问Class对应的类所包含的属性

//方法1
Field getField(String name);
返回此Class对象所表示的类的指定的public属性,name参数指定属性名称

该方法将返回此Class对象所表示类的指定的public属性
//方法2
Field[] getFields();
返回此Class对象所表示的类的所有public属性

//方法3

Field getDeclaredField(String name);
返回此Class对象所表示的类的指定属性,与属性的访问级别无关

//方法4
Field[] getDeclaredFields();
返回此Class对象所表示的类的全部属性,与属性的访问级别无关

访问Class对应的类所包含的注释
<A extendsd Annotation> A getAnnotation(Class<A> annotationClass)
试图获取该Class对象所表示类上指定类型的注释,如果该类型的注释不存在则返回null,其中annotationClass参数对应注释类型的Class对象

Annotation[] getAnnotations();返回此元素上存在的所有注释
Annotation[] getDeclaredAnnotations(); 返回直接存在于此元素上的所有注释

如何访问Class对应的类所包含的内部类
Class[] getDeclaredClasses();
返回此Class对象所对应的类里包含的全部内部类,如果Class对象所对应的类是一个内部类,那我们如何得知Class所对应的外部类呢?

访问Class对应的类所在的外部类
Class getDeclaringClass();
返回此Class对象所在的外部类

注意:访问内部类与访问所在外部类的方法名称差不多,一定要注意他们的方法名称

如下的方法用于访问该Class对象所对应类所继承的父类,所实现的接口等



上面的getModifiers()返回的修饰由public protected private final static abstract等对应的常量 组成 返回的整数应使用Modifier工具类的方法来解码,才可以获取真实的修饰符







创建对象



上面三个对象都在java.lang.reflect包下,都实现了java.lang.reflect.Member接口

可以通过Constructor对象来调用相应的构造方法创建对象

通过Field对象直接访问并修改对象的属性值

如何通过反射创建对象

1.使用newInstance()创建对象

2.使用Constructor对象创建对象





实际上,只有当程序需要动态创建某个类的对象是才会考虑到使用反射,通常在开发通用性比较广的框架、基础平台时可能会大量使用反射,因为在很多Java EE框架中都需要根据配置文件信息来创建Java对象,从 配置文件读取的只是某个类的字符串类名,程序想根据字符串来创建对应的实例,就必须使用反射,如我们所知道的Spring框架就应用了这个技术

反射技术多用于框架即基础平台中

使用Constructor()创建对象

如果我们不想利用默认构造方法来创建java对象,而想利用指定的构造方法来创建java对象,则需要利用Constructor对象了,每个Constructor对应一个构造方法,利用指定构造方法来创建java对象需要三个步骤:

1.获取该类的Class对象

2.利用Class对象的getConstructor()方法来获取指定构造方法

3.调用Constructor的newInstance()方法来创建java对象




如何使用反射调用方法:





实例:





在调用方法时如何传参数



如果我们把Person类的setName方法的访问权限设为私有,这时再运行程序,则会抛出NoSuchMethodexception异常,这时因为当通过Method的invoke()方法调用对应的方法时

java会要求程序必须有调用该方法的权限,如果程序确实需要调用某个对象的private方法,可以先调用setAccessible(Boolean flag)方法,将Method对象的accessible标志设置为指示的布尔值,值为true则表示该Method在使用时用该取消java语言的访问权限检查,值为false则表示该Method在使用时应该实施java语言访问权限检查



如何访问属性









File.setAccessible(true);

我们对获取到的私有属性调用方法setAccessible(true),便可以使用这两个方法随意的访问指定对象的所有属性,包括private访问控制属性

访问Person类中的属性



通过反射获取Person类中的属性


事实上在实际开发中,我们没有必要使用反射,来访问已知类的方法和属性,只有当程序需要动态创建某个类的对象的时候我们才会考虑使用反射,例如,我们要从配置文件中读取以字符串形式表示的类时,我们就要使用反射来获取他的方法和属性了,



又比如,我们可以使用反射来写一个,在Action中接受参数的公共方法,这样不同的Action在接收参数时,只需要调用接收参数的公共方法就可以了,而不必每次都为没一个参数写一句request.getParameter语句了



动态创建和访问数组

在java.lang.reflect包下还提供了一个Array类,Array对象可以代表所有的数组,程序可以通过使用Array来动态的创建数组,并且操作数组的元素

Array类提供了如下几类方法:

1.通过newInstance() 方法我们可以创建一个具有指定的元素类型、指定唯独的数组



2.getXxx()方法,将返回Array数组中的第index个元素,这与使用反射返回属性类似



3.



下面实例如何使用这些方法来动态的创建和访问数组


只用三行代码就完成了动态创建数组及访问数组



使用Array类来创建多维数组



总结:

在反射机制概述中,我们了解到了java的一个动态特性:反射 知道了反射机制是一种动态获取信息以及动态调用对象方法的功能,通过反射我们可以在运行时判断任意一个对象所属的类,在运行时构造任意一个类的对象,判断任意一个类所具有的方法和属性,同时,也可以在运行时调用任意一个对象的方法以及生成动态代理,如果编译时我们根本无法预知该对象或类可能属于哪些类,程序只能依靠运行时信息来发现该对象和类的真实信息,那么此时我们就必须使用反射,事实上,在我们平时写代码的时候反射技术用的并不是很多,因为通过反射创建对象时性能要稍微低一些,只有当程序需要动态创建某个类的对象时才会使用反射Class类是反射的核心类,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: