java反射机制讲解及示例

java反射机制作用:在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象在运行时判断任意一个类所具有的成员变量和方法在运行时调用任意一个对象的方法Reflection是java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(修饰符,诸如public,static等等),superclass(父类,例如Object),实现之interfaces(接口,例如Serializable),也包括fields(成员变量)和methods(方法)的所有信息,并可于运行时修改fields内容或调用methods。通过反射可以去改变一个私有方法,一个私有成员变量(打破类的包装机制)

程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言:Perl,Python,Rudy是动态语言,C++,java,C#不是动态语言。(如图,javaScript是动态语言)

尽管java不是动态语言,但却有个非常突出的动态相关机制:反射,意思是指我们可以在运行时加载,探知,使用编译期间完全未知的classes。(即java可以加载一个运行时才知道其名称的类,获悉其完整构造(不包括methods定义,只能得到方法声明),并生成其对象实体,或对其fields设值,或唤起其methods)。这种看透class的能力称为introspection。java的反射机制,需要使用java.lang.reflect包:-Class类:代表一个类-Fields类:类的成员变量(类属性)-Method类:代表类的方法-Constructor类:类的构造方法-Array类:提供了动态创建数组,以及访问数组的元素的静态方法反射时,前面四个类是一定会用到的

这个方法可以获得所有方法描述。类似的有getDeclaredFields();

例子DumpMethod.java:读取命令行参数指定的类名,然后打印这个类所具有的方法信息。

package com.wws.reflect;import java.lang.reflect.Method;public class DumpMethod {public static void main(String[] args) throws Exception{//获得String的类Class<?> classType =Class.forName("java.lang.String");//获得并返回类的所有方法Method[] methods =classType.getDeclaredMethods();for(Method method:methods){System.out.println(method);}}}

结果:

改为获取传入实体的类方法信息:

package com.wws.reflect;import java.lang.reflect.Method;public class DumpMethod2 {public static void main(String[] args) throws Exception{//获得命令行输入类名的类型Class<?> classType =Class.forName("arg[0]");//获得并返回类的所有方法Method[] methods =classType.getDeclaredMethods();for(Method method:methods){System.out.println(method);}}}

传人参数:

效果:

接下来写个简单程序

用反射改造:

package com.wws.reflect;import java.lang.reflect.Method;import java.sql.ResultSet;public class InvokeTester {public int add(int parm1,int parm2){return parm1+parm2;}public String echo(String message){return "hello:"+message;}public static void main(String[] args)throws Exception{/*获取java类的几种方法:通过Class类的静态方法:forName(XX);String.class,getClass()*/Class<?> classType= InvokeTester<strong>.class</strong>;Object invokeTester =classType.<strong>newInstance()</strong>;/*System.out.println(invokeTester instanceof InvokeTester);返回true*//*Method java.lang.Class.<strong>getMethod(String name, Class<?>... parameterTypes)</strong>参数一:目标方法名参数二:目标方法的参数类型数组*/Method addMethod=classType.getMethod("add", new Class[]{int.class,int.class} );/*调用invoke实现对目标方法的调用 * 参数一:实例名 * 参数二:接受什么参数 * */Object result=addMethod<strong>.invoke(invokeTester,new java.lang.Object[]{1,2});</strong>System.out.println((Integer)result);Method echoMethod=classType.getMethod("echo", new Class[]{String.class});Object result2=echoMethod.invoke(invokeTester, new Object[]{"wws"});System.out.println((String)result2);}}

运行结果:

通过Class类的静态方法:

forName(XX);String.class;

getClass();

newInstance()不会生成带参数方法的实例,此时应该用Constructor的newInstance(Object …initargs),即用类getConstructor(new Class[ ] { }).newInstance(new Object[ ]{ });

例子2:实现get,set方法:

public class CopyObject {     public Object copyObject(Object object) throws Exception {         // 1.获取待操作类的一个Class对象        Class<?> classType = object.getClass();         // 2.获取待操作类的一个实例        Constructor<?> constructor = classType                .getConstructor(new Class<?>[] {});        Object copyObj = constructor.newInstance(new Object[] {});         // 3.获取被拷贝类的成员变量        Field[] fields = classType.getDeclaredFields();         for (Field field : fields) {            // 4.遍历数组获取各个成员变量名字            String name = field.getName();// 获取成员变量名字;             // 5.操作字符串获取成员变量的set和get方法名字;            String firstLetter = name.substring(0, 1).toUpperCase();            String getMethodName = "get" + firstLetter + name.substring(1);            String setMethodName = "set" + firstLetter + name.substring(1);             Method getMethod = classType.getMethod(getMethodName,                    new Class<?>[] {});            Method seMethod = classType.getMethod(setMethodName,                    new Class<?>[] { field.getType() });                         /*最开始认为以下两个invoke方法的第一和参数都应该调用copyObj,             * 但是最终的结果为输出为默认的空值。             * copyObj:程序前面通过Constructor类的newInstance方法             * 获取待操作类的一个实例;            //Object value = getMethod.invoke(copyObj, new Object[] {});            //seMethod.invoke(copyObj, new Object[] { value });             /*现在改用如下方式了,输出就正常了             * 所以产生疑惑:为什么第一个方法调用的object对象而不是copyObj呢?             *              */            Object value = getMethod.invoke(object, new Object[] {});            seMethod.invoke(copyObj, new Object[] { value });                      }         return copyObj;    }     public static void main(String[] args) throws Exception {         Student student = new Student("Tom", 21);        student.setId(111030805);        CopyObject copy = new CopyObject();        Student student2 = (Student) copy.copyObject(student);        System.out.println(student2.getId() + " " + student2.getName() + " "                + student2.getAge());    }} // 一个被反射的JavaBeanclass Student {     private long id;    private String name;    private int age;     public Student() {     }     public Student(String name, int age) {        this.name = name;        this.age = age;    }     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 long getId() {        return id;    }     public void setId(long id) {        this.id = id;    } }更多 0

反射生成数组:

生成多维数组:

输出结果:37,创建了一个5,10,15的三维数组。

利用反射调用类的私有方法:

到底通向了什么样的远方呢?

java反射机制讲解及示例

相关文章:

你感兴趣的文章:

标签云: