反射

时间:2016-11-5 21:59

1、反射的原理
    反射应用在一些通用性比较高的代码中。
    绝大多数Java框架都是通过反射来实现的。
    在框架开发中,都是基于配置文件进行开发。
        在配置文件中配置了类之后,可以通过反射来得到类中的所有内容,可以执行类中的某个方法,不需要创建对象。

    类中的内容:
        无参构造
        有参构造
        成员属性

        成员方法

    分析反射原理:
        首先需要把Java文件保存到本地硬盘。
        编译java文件,生成.class字节码文件。
        使用JVM,把class文件通过类加载到内存中。
        class文件在内存中使用Class类表示。
        当使用反射的时候,首先需要获取到Class类,得到这个类的对象之后,就可以得到这个类的所有内容。
            包括构造方法、属性、普通方法。
        构造方法:Constructor
        属性:Filed
        普通方法:Method

2、使用反射获取Class类对象

    //获取Class类
    Class p1 = Person.class;
    Class p2 = new Person().getClass();
    Class p3 = Class.forName("fanshe.Person");

    要对一个类进行实例化,如果不使用new,怎么获取?
        Person p = (Person) Class.forName("fanshe.Person").newInstance();
 

3、操作有参数的构造方法:

    构造方法必须是public。

    //得到Class类对象
    Class c = Class.forName("fanshe.Person");
    //得到所有的构造方法(不常用)
    //c.getConstructors();
    //根据参数列表获取构造方法,传递的参数是参数类型的类
    Constructor cs = c.getConstructor(String.class, String.class);
    //此时已经获取到有参构造方法
    //使用有参构造方法创建对象
    Person p = (Person)cs.newInstance("张三","1");
    //获取Person属性
    System.out.println(p.getName());

4、使用反射操作属性
    //得到Class类
    Class c = Class.forName("fanshe.Person");
    //得到Person类实例
    Person p = (Person) c.newInstance();    //需要执行强制类型转换
    //获取所有属性(不常用)
    //Field[] f = c.getDeclaredFields();
    //得到name属性
    Field name = c.getDeclaredField("name");
    //将私有属性设置为可访问(私有属性默认为false,不允许操作)
    name.setAccessible(true);
    //设置name值
    name.set(p, "王五");//相当于p.name = "王五",第一个参数是实例对象,第二个参数是赋值的值
    //获取name值
    System.out.println(name.get(p));//相当于p.name,传递的参数是实例对象

/***************************************************************************/
getDeclaredField是可以获取一个类的所有字段. 
getField只能获取类的public 字段
/***************************************************************************/ 

5、使用泛型操作普通方法
    使用Method类表示普通方法。(setName)

    //得到Class类
    Class c = Class.forName("fanshe.Person");
    //获取Person实例
    Person p = (Person)c.newInstance();
    //得到所有的普通方法(不常用)
    //c.getDeclaredMethods();
    //得到setName(),第一个参数是方法名,第二个参数是参数类型的类
    Method m = c.getDeclaredMethod("setName", String.class);
    //如果操作的是私有方法,需要将访问权限设置为true
    m.setAccessible(true); 
    //执行Method方法
    m.invoke(p, "赵六");    //第一个参数是实例对象,第二个参数是方法参数
    //获取getName()
    Method g = c.getDeclaredMethod("getName");
    //执行getName方法
    System.out.println(g.invoke(p));

    当操作的方法是静态方法的时候,就不需要创建实例了,可以直接通过类名来调用。
    当使用反射操作静态方法的时候,也不需要实例对象:
        m.invoke(null, "哈哈");
    参数为null,表示这是一个静态方法。

6、方法总结
    Class  forName(String  ClassURL)
        获取类对象。
    Constructor  getConstructor(Object...)
        获取构造方法。
    Object  newInstance(Object...)
        创建实例对象。
    Field  getDeclaredField(String FieldName)
        根据名称获取属性。
    void  setAccessiable(boolean  flag)
        设置私有属性是否可以访问。
    void  set(Object obj, Object value...)
        执行指定实例对象的方法。
            obj:实例对象
            value:方法参数
    void  get(Object obj)
        执行指定实例对象的方法。
    Method  getDeclaredMethod(String methodName, Class argsClass...)
        根据方法名和参数列表获取方法。
    void  invoke(Object obj, Object value...)
        执行指定实例的方法,并传递参数列表。
原文地址:https://www.cnblogs.com/wwwwyc/p/6375236.html