1. Java的反射机制
动态语言是指在程序运行时允许改变程序结构或者变量类型,从这个观点看,JAVA和C++一样,都不是动态语言。但Java它却有着一个非常突出的动态相关机制:反射。
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能:
(1)在运行时判断任意一个对象所属的类;
(2)在运行时构造任意一个类的对象;
(这一条在下面没有展示实例,但在之前写过的一篇Java中创建对象的5种方式中有所介绍,有兴趣的可以参考查看。)
(3)在运行时判断任意一个类所具有的成员变量和方法;
(4)在运行时调用任意一个对象的方法;
(5)生成动态代理。
2. Java反射API
反射API用来生成在当前Java虚拟机中的类、接口或者对象的信息。
Class类:反射的核心类,可以获取类的属性,方法等内容信息。
Field类:Java.lang.reflect.表示类的属性,可以获取和设置类的中属性值。
Method类:Java.lang.reflect。表示类的方法,它可以用来获取类中方法的信息或者执行方法
Construcor类:Java.lang.reflect。表示类的构造方法。
3.反射常见用法
3.1 判断对象是否属于反射得到的类(isInstance)
class S { } public class IsInstance { public static void main(String args[]) { try { Class cls = Class.forName("S"); //创建了一个S类的Class对象 boolean b1 = cls.isInstance(new Integer(37)); System.out.println(b1); //fasle boolean b2 = cls.isInstance(new S()); System.out.println(b2); //true } catch (Throwable e) { System.err.println(e); } } }
3.2 获取某个反射类的所有属性字段
/** * 获取反射类的所有属性字段 * * @param ownerClass 反射的类 * @return * @throws Exception */ public Field[] getProperty(Class ownerClass) throws Exception { //获取该类所有属性字段 //Field[] fields = ownerClass.getFields();//只获取public访问权限的属性字段(包括父类的) Field[] fields = ownerClass.getDeclaredFields();//只获取该类的所有访问权限的属性(不含父类) //输出所有属性字段 for(int i=0;i<fields.length;i++){ System.out.println("属性:"+fields[i]); } return fields; }
3.3 获取反射类的某个public属性值
/** * 获取反射类的某个public属性值 * * @param ownerClass 反射的类 * @param fieldName 属性名 * @return * @throws Exception */ public Object getProperty(Object owner,String fieldName) throws Exception { //得到对象所属类 Class ownerClass = owner.getClass(); //获取该类的某个属性 Field field = ownerClass.getField(fieldName); //获取某个对象的特定属性 Object property = field.get(owner); //输出该属性信息 System.out.println(fieldName+"的属性值:"+property.toString()); return property; }
3.4 获取反射类的该中的所有方法
/** * 获取反射类的该中的所有方法 * @param ownerClass 反射的类 * @return * @throws Exception */ public Method[] getMethods(Class ownerClass) throws Exception { //获取该类所有方法 //Field[] fields = ownerClass.getMethods();//只获取public访问权限的方法(包括父类的) Method[] methods = ownerClass.getDeclaredMethods();//只获取该类的所有访问权限的方法(不含父类) //输出所有方法 for(int i=0;i<methods.length;i++){ System.out.println("方法:" +methods[i]); } return methods; }
3.5 执行反射类的该中的某个方法
/** * 执行反射类的该中的某个方法 * @param ownerClass 反射的类 * @param methodName 方法名 * @return * @throws Exception */ public Object invokeMethod(Object owner,String methodName,Object[] args) throws Exception { //得到对象所属类 Class ownerClass = owner.getClass(); //获取该类的某个方法 Method method = ownerClass.getMethod(methodName, null); //执行某个对象的方法 Object result = method.invoke(owner, args); //输出结果信息 System.out.println("结果返回值:"+ result); return result; }
实例演示方法:
/** * 测试反射常用方法 */ public void refTest(){ String className = "com.java.reflecttest.Student"; try { //通过反射机制,使用类装载器,装载该类 Class<?> stu = Class.forName(className); Object objStu = stu.newInstance(); //获取反射类的所有属性 System.out.println(" >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "); System.out.println("调用 getProperty 方法,获取Student类的所有属性"); getProperty(stu); //获取反射类的某个属性值 System.out.println(" >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "); System.out.println("调用 getProperty 方法,获取Student类的NAME属性值"); getProperty(objStu,"NAME"); //获取反射类的所有方法 System.out.println(" >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "); System.out.println("调用 getMethods 方法,获取Student类的所有方法"); getMethods(stu); //执行反射类的getInfo方法 System.out.println(" >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "); System.out.println("调用 invokeMethod 方法,执行Student类的getInfo方法"); invokeMethod(objStu, "getInfo", null); } catch (Exception e) { e.printStackTrace(); } }
演示所用的Student类:
package com.java.reflecttest; /** * 学生信息类 * * @author Longxuan * */ public class Student { /** * 学号 */ private String stuId ; /** * 学号 */ public String STUID; /** * 姓名 */ private String name ; /** * 姓名 */ public String NAME; /** * 年龄 */ private int age; /** * 年龄 */ public int AGE; /** * 班级 */ private String classid; public String getStuId() { return stuId; } public void setStuId(String stuId) { this.stuId = stuId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getClassid() { return classid; } public void setClassid(String classid) { this.classid = classid; } /** * 输出学生信息 */ public void getInfo(){ System.out.println("学生信息: 学号:"+stuId+" 姓名:"+name+" 年龄:"+age+" 班级:"+classid); } /** * 构造函数 */ public Student(){ init(); } /** * 私有初始化方法 */ private void init(){ this.name = "张三"; this.stuId ="1001"; this.age = 14; this.classid = "A001"; this.NAME = name; this.AGE = age; this.STUID = stuId; } }
运行结果:
4. 反射的效率
在Stackoverflow上认为反射比较慢的程序员主要有如下看法,如果你面试遇到了,可以这样回答:
(1)验证等防御代码过于繁琐,这一步本来在link阶段,现在却在计算时进行验证。
(2)产生很多临时对象,造成GC与计算时间消耗。
(3)由于缺少上下文,丢失了很多运行时的优化,比如JIT(它可以看作JVM的重要评测标准之一)
当然,我个人的看法是,现代JVM也不是非常慢了,它能够对反射代码进行缓存以及通过方法计数器同样实现JIT优化,所以反射不一定慢。更重要的是,很多情况下,你自己的代码才是限制程序的瓶颈。因此,在开发效率远大于运行效率的的基础上,大胆使用反射,放心开发吧。
文章转自:http://blog.csdn.net/xiaoxian8023/article/details/9206055
http://www.jianshu.com/p/f83556bcae59