Java反射机制

来源:互联网 发布:权志龙的淘宝店叫什么 编辑:程序博客网 时间:2024/05/20 10:53
                     Java反射机制

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

作用:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

反射机制在API 需要的类:
java.lang.Class;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;

下面我们通过几个实例来描述java反射机制都能做哪些事情。

利用反射机制对ReflectTester类的customer对象进行拷贝:

  import java.lang.reflect.Field;import java.lang.reflect.Method;public class ReflectTester {    // 该方法实现对 customer对象的拷贝    public Object copy(Object object) throws Exception {        Class<?> classType = object.getClass();//获得 Object类的类对象        Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});        // 先通过类对象对不带参数的构造方法获得其constructor对象,再通过构造方法对象        // 调用实例化方法生成对customer类的对象,并转成object类型的 所以objectCopy是object类型的引用        // ,但指向customer类,也就是多态。        // Object object2=classType.newInstance();上面两句等同于这一句        Field[] fields = classType.getDeclaredFields(); // 获得指定类(Object)的所有成员变量        for (Field field : fields) { // 增强的for循环 对存储customer成员变量的数组进行遍历 ,并打印输出            String name = field.getName();            String firstLetter = name.substring(0, 1).toUpperCase();// substring方法是获得对应字符串的在该下标范围内的字符 [0,1)                                                                    // toUpperCase方法是将属性的首字母转换成大写            String getMethodName = "get" + firstLetter + name.substring(1);// 这个1表示1到末尾的字符            String setMethodName = "set" + firstLetter + name.substring(1);//字符串拼接            Method getMethod = classType.getMethod(getMethodName, new Class[] {});// customer类里面的getName方法是无参方法,获得指定方法的方法对象,括号内的getMethodName就是我们想要获得的方法的方法名,后面的Class类的数组就是该方法的参数            Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });// setMethodName方法是有参方法,getType方法是返回field的类型            Object value = getMethod.invoke(object, new Object[] {});// 这里的object是一开始传入的customer,getName方法无参,也就是通过invoke方法调用指定的方法,也就是Customer类里面的所有成员变量的get方法,最后得到object对象里面的具体数值信息然后赋给value对象,            setMethod.invoke(objectCopy, new Object[] { value });// 将value里面的值传给objectCopy对象,通常情况下只要我们new一个对象,该对象里面都会包含一份对应类的成员变量,我们将面从get方法里面返回的数值重新赋给objectCopy里面的成员变量,也就完成了copy操作        }        return objectCopy;    }    public static void main(String[] args) throws Exception {        Customer customer = new Customer("Tom", 20);        customer.setId(1L);        ReflectTester test = new ReflectTester();        Customer customer2 = (Customer) test.copy(customer);        System.out.println(customer2.getId() + "," + customer2.getName() + "," + customer2.getAge());    }}class Customer {    private Long id;    private String name;    private int age;    public Customer() {    }    public Customer(String name, int age) {        this.name = name;        this.age = age;    }    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    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;    }}  

代码中的注释对代码解释已经很详细我就不在说了。接下来在看第二个例子,功能是实现调用某类的方法:

这里写import java.lang.reflect.Method;public class InvokeTester{    public int add(int param1, int param2)    {        return param1 + param2;    }    public String echo(String message)    {        return "hello: " + message;    }    public static void main(String[] args) throws Exception    {        // InvokeTester test = new InvokeTester();        // System.out.println(test.add(1, 2));        // System.out.println(test.echo("tom"));        //下面那么多行代码其实就等同于上面几行代码        Class<?> classType = InvokeTester.class;//获得对应类的类对象        Object invokeTester = classType.newInstance();//获得指定类的实例        // System.out.println(invokeTester instanceof InvokeTester);        Method addMethod = classType.getMethod("add", new Class[] { int.class,int.class });//通过括号内的限制,获得指定方法的方法对象        Object result = addMethod.invoke(invokeTester, new Object[]{1, 2});//对指定方法进行调用,        System.out.println(result);        System.out.println("---------------------");        Method echoMethod = classType.getMethod("echo", new Class[]{String.class});        Object result2 = echoMethod.invoke(invokeTester, new Object[]{"tom"});        System.out.println((String)result2);    }}

再看第三个例子,功能是给某类的私有变量赋值:

public class Private2{    private String name = "zhangsan";    public String getName()    {        return name;    }}import java.lang.reflect.Field;public class TestPrivate2{    public static void main(String[] args) throws Exception    {        Private2 p = new Private2();        Class<?> classType = p.getClass();//获得指定类的类对象        Field field =classType.getDeclaredField("name");//获得指定类里面的指定成员变量        field.setAccessible(true);//这里很重要,这里就使我们为什么能对私有化成员变量进行修改的主要原因,不明白得就去查看API文档        field.set(p, "lisi");//修改指定成员变量的值        System.out.println(p.getName());    }}

下一个例子是通过反射构建数组

import java.lang.reflect.Array;public class ArrayTester1 {    public static void main(String[] args) throws Exception {        Class<?>classTypeClass.forName("java.lang.String");//根据后面的字符串获得指定类的类对象        Object  array = Array.newInstance(classType, 10);//这里的classtype是String,这句话的意思是创建一个String类型长度为10的数组        System.out.println(array instanceof String[]);        for(int i=0;i<Array.getLength(array);i++) {            String str = (String) Array.get(array, i);            System.out.println(str);        }        Array.set(array, 5, "hello");//对数组某个位置上添加元素        String str = (String) Array.get(array, 5);        System.out.println(str);    }}

也不知道你们有没有耐心看到这里。。。。。。。

最后我就在总结一下反射机制的用法:

一般情况下 只要使用反射机制,我们都会先获得对应类的类对象,而获得类对象有三种方法:

a)使用 Class 类的静态方法 forName:Class.forName(“java.lang.String”);b)使用类的.class 语法:String.class;c)使用对象的 getClass()方法:String s = “aa”; Class<?> clazz = s.getClass();

若想通过类的不带参数的构造方法来生成对象,我们有两种方式:

a)先获得 Class 对象,然后通过该 Class 对象的 newInstance()方法直接生成即可:Class<?> classType = String.class; Object obj = classType.newInstance();b)先获得 Class 对象,然后通过该对象获得对应的 Constructor 对象,再通过该 Constructor 对象的 newInstance()方法生成:Class<?> classType = Customer.class;Constructor cons = classType.getConstructor(new Class[]{}); Object obj = cons.newInstance(new Object[]{});

若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:

Class<?> classType = Customer.class;Constructor cons = classType.getConstructor(new Class[]{String.class, int.class}); Object obj = cons.newInstance(new Object[]{“hello”, 3});

至于一些其他的方法也基本都在上面代码中,我就不在一一列出来。
不正确的地方大家多多指教。