反射机制使用解析

一、反射机制是什么?

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。其实反射就是学习一个叫Class的类,这个特殊的类可以对其他类进行操作。

二、通常用反射做什么?

判断对象是否属于某个类,获取一个类对象对应类的成员属性,构造方法和成员方法,获取属性的修饰符或类型,获取方法的修饰符和方法的返回类型,在运行时实例化对象,调用任意一个类的方法,或者对任意一个类的属性进行操作等等。

下面的代码以下面这个类做讲解:

public class Reflect implements Serializable{

    static class Student{
        private String name;
        private int age;

        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public Student() { 
        }

        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 void StudentReflect1(){
            System.out.println("无参数的方法");
        }
        public void StudentReflect2(String name,int age){
            System.out.println(name+" "+age);
        }
    }
}

三、反射相关API的使用

① 获取对象完整的的包名和类名

Student stu = new Student();
//查看完整的包名.类名
System.out.println(stu.getClass().getName());

或者可以

Class<?> clazz = Class.forName("Reflect");

② 获取父类或接口

//Class类的父类是Object类,getSuperClass()就是获取父类对象                System.out.println(clazz.getSuperclass().getName());
            //获取类的各个接口
            Class<?> interfaces[] = clazz.getInterfaces();
            for(Class c : interfaces){
                System.out.println("接口有:"+c.getName());
            }

③ 获取类的构造方法并实例化对象

//获取类的各个构造方法
            Constructor<?> cons[] = stu.getClass().getConstructors();
            for(int i = 0; i < cons.length; i++){
                Class<?>[] clazzs = cons[i].getParameterTypes();
            }
            stu = (Student) cons[1].newInstance("惠惠",21);
            //通过类的对象获得类的实例化对象操作
            stu = (Student)stu.getClass().newInstance();

④ 获取类的属性的修饰语、属性的类型、属性名

clazz = stu.getClass();
        //获取本类的属性的数组集合,getFields()是获取父类的属性
        Field f[] = clazz.getDeclaredFields();
        for(int i = 0; i < f.length; i++){
            //获取属性的修饰语
            int mo = f[i].getModifiers();
            String modi = Modifier.toString(mo);
            //获取属性的类型
            Class<?> type = f[i].getType();
            System.out.print("权限修饰符:"+modi+" ");
            System.out.print("属性类型:"+type.getName()+" ");
            System.out.println("属性名:"+f[i].getName()+" ");
        }

⑤ 获取类的方法并执行方法

//获取类的方法
        Method methods[] = clazz.getMethods();
        for(int i = 0; i < methods.length; i++){
            System.out.println(methods[i].getModifiers()+" "+methods[i].getName());
        }
        //通过反射调用类的方法,注意不是构造方法
        Method m = clazz.getMethod("StudentReflect1");
        //唤醒(执行该方法)
        m.invoke(clazz.newInstance());
        //获取指定方法
        m = clazz.getMethod("StudentReflect2", String.class,int.class);
        //使用invoke实例化对象,并传入指定的参数到给该对象,最终执行该方法
        m.invoke(clazz.newInstance(), "刘德华",22);

⑥ 操作类的属性

Class<?> clazz = stu.getClass();
Field nameField = clazz.getDeclaredField("name");
        Field ageField = clazz.getDeclaredField("age");
        Object obj = clazz.newInstance();
        //将modifier为private的属性设置为可访问
        nameField.setAccessible(true);
        ageField.setAccessible(true);
        nameField.set(obj, "刘德华");
        ageField.set(obj, 23);
        System.out.println(nameField.get(obj));
        System.out.println(ageField.get(obj));

四、其他的一些使用

反射给存放Integer类型对象的容器存放String类型对象:

//使用反射可以给一个装Integer对象的容器添加进String类型的对象
        List<Integer> list = new ArrayList<Integer>();
        Method me = list.getClass().getMethod("add", Object.class);
        me.invoke(list,"反射机制");
        for(int i = 0 ; i < list.size(); i++){
            System.out.println(list.get(i));
        }

获取操作数组的信息:

//反射获取数组的类型
        int arr[] = {1,2,3,4};
        Class<?> cla = arr.getClass().getComponentType();
        System.out.println("数组类型:"+cla.getName());
        System.out.println("数组长度:"+Array.getLength(arr));
        System.out.println(Array.get(arr, 0));
        //对数组指定索引处的值进行修改
        Array.set(arr, 0, 5);
        System.out.println(Array.get(arr, 0));

修改数组的长度:

int arr[] = {1,2,3,4};
System.out.println("------------------反射修改数组大小---------------");
        System.out.println("arr的数组长度为:"+arr.length);
        int newArr[] = (int [])arrayInc(arr,5);
        System.out.println("增加后的arr的数组长度为:"+newArr.length);

public static Object arrayInc(Object obj,int len){
        //获取数组的Class类的对象
        Class<?> arr = obj.getClass().getComponentType();
        int originalLen = Array.getLength(obj);
        Object newArr = Array.newInstance(arr, originalLen+len);
        System.arraycopy(obj, 0, newArr, 0, originalLen);
        return newArr;
    }

还有运用于工厂模式和动态代理,不过暂时还搞不懂先Mark一下
参考文章:http://baike.xsoftlab.net/view/209.html#3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值