java基础之反射

package zy.refactor;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/*
 * 反射:主要作用于访问一个类的私有字段和私有方法
 * 使用流程1(已知类的字段以及方法):
 *         A:获取对象Class
 *         B:实例化对象
 *         C:根据字段名反射私有字段  class.getDeclaredField(字段名)
 *         D:打开允许访问的开关 setAccessible(true);
 *         E:赋值(set): name.set(dog, "二哈");  访问(get):    name.get(dog)
 *         F:根据方法名反射私有方法cls.getDeclaredMethod("eat", String.class, String.class);
 *         G:打开开关
 *         H:访问私有方法  m2.invoke(dog, "阿拉斯加", "全家桶");
 * 使用流程2(不知道类的字段及方法):
 *         A:获取对象Class
 *         B:根据Class反射所有的字段名称以及类型(循环Field[]得出字段名以及字段类型)
 *         C:根据Class反射构造方法
 *         D:根据构造方法创建对象(object类型)
 *         E:根据B中得到的字段名称和类型分别定义Field并打开开关然后给私有字段赋值 Field name = cls.getDeclaredField("name");
 *         F:访问私有字段
 *         G:反射私有方法(也可以反射Method[]数组 循环得出方法名等,类似反射字段数组)
 *         H:打开开关并访问私有方法
 */
/**
 * 反射的应用
 * 
 * @author zy
 * @version 1.0
 */
public class RefectorDemo {
    public static void main(String[] args) throws Exception {
        // 获取类的字节码对象(获取对象Class) 以下方法都可以
        // Class cls = dog.getClass();
        // Class cls = Dog.class;
        Class cls = Class.forName("zy.refactor.Dog");
        // -------------------------------------------------------方式1
        // 创建对象
        Dog dog = new Dog();

        // 反射私有字段
        Field name = cls.getDeclaredField("name");
        Field age = cls.getDeclaredField("age");

        // 打开开关
        name.setAccessible(true);
        age.setAccessible(true);

        // 赋值
        name.set(dog, "二哈");
        age.set(dog, 6);

        // 访问私有字段
        System.out.println(name.get(dog) + "--" + age.get(dog));

        // 反射私有方法
        Method m1 = cls.getDeclaredMethod("eat");
        Method m2 = cls.getDeclaredMethod("eat", String.class, String.class);

        // 打开开关
        m1.setAccessible(true);
        m2.setAccessible(true);

        // 访问私有方法
        m1.invoke(dog, null);
        m2.invoke(dog, "阿拉斯加", "全家桶");

        // -----------------------------------------------------------------下面是方式2
        System.out.println("----------------------------");
        // 反射所有的字段名称
        Field[] fields = cls.getDeclaredFields();
        // 此时已经知道一共有多少字段分别为什么 可以根据字段名称以及字段类型 进行赋值
        for (Field f : fields) {
            System.out.println(f.getType() + "--" + f.toString());
        }
        // 此时我们已经知道Dog类中有两个私有的字段,分别为String类型的name和int类型的age;下面我们就直接用了

        //反射所有方法 和反射字段基本类似
        Method[] methods = cls.getDeclaredMethods();
        for (Method m : methods) {
            System.out.println(m.getName());
        }
        
        
        // 反射构造方法
        Constructor con1 = cls.getConstructor();
        Constructor con2 = cls.getConstructor(String.class, int.class);

        // 根据反射的构造方法创建对象
        Object obj1 = con1.newInstance();// 创建对象
        Object obj2 = con2.newInstance("泰迪", 3);// 创建对象并赋值

        // obj1用的空构造方法
        // 给obj1对象的字段赋值(因为上面循环fields已经知道了这两个字段的name和type,这里就直接赋值了)
        name.set(obj1, "金毛");
        age.set(obj1, 4);

        // 访问私有字段
        System.out.println(name.get(obj1) + "--" + age.get(obj1));// 金毛--4
        System.out.println(name.get(obj2) + "--" + age.get(obj2));// 泰迪--3
        // 访问私有方法
        m1.invoke(obj1, null);
        m2.invoke(obj1, name.get(obj1), "金毛的食物");
        m1.invoke(obj2, null);
        m2.invoke(obj2, name.get(obj2), "泰迪的食物");

    }
}


package zy.refactor;

/*
 * 反射用的dog类
 */
public class Dog {
    private String name;
    private int age;

    public Dog() {
    }

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

    private void eat() {
        System.out.println("狗吃骨头");
    }

    private void eat(String name, String food) {
        System.out.println(name + "吃" + food);
    }
}

 

posted @ 2016-02-28 15:31  青衫仗剑  阅读(296)  评论(0编辑  收藏  举报