反射学习笔记

来源:互联网 发布:什刹海 知乎 编辑:程序博客网 时间:2024/06/10 03:16



反射技术:动态的获取指定的类以及动态的调用类中的内容。
在一个应用程序已经写好时,后期出现的接口类无法直接在该应用程序中用new创建对象。该怎么办?既然子类不确定,可以通过配对外提供配置文件中的形式,将不确定的信息存储到配置文件中即可。该程序只要之前写好如何读取配置文件信息即可。
如果存储了指定的子类名,就根据具体的名称找该类并进行加载和对象的创建,这些动作都在前期定义软件时写好的。没有类之前就将创建对象的动作完成了,这就是动态的获取指定的类,并使用类中的功能。这就是反射技术。反射技术的出现大大的提高了程序的扩展性。类不确定时都会用到反射技术。

Field field:将字段封装成对象类型 Field。
Constructor  cons ;将构造函数封装成了对象类型  Constructor。
Method  method ;将类中的成员都封装成了对象。
还提供了对这些成员的操作。
getField()
getContructor()

在一个应用程序已经写好时,后期出现的接口类无法直接在该应用程序中用new创建对象。该怎么办?既然子类不确定,可以通过配对外提供配置文件中的形式,将不确定的信息存储到配置文件中即可。该程序只要之前写好如何读取配置文件信息即可。
如果存储了指定的子类名,就根据具体的名称找该类并进行加载和对象的创建,这些动作都在前期定义软件时写好的。没有类之前就将创建对象的动作完成了,这就是动态的获取指定的类,并使用类中的功能。这就是反射技术。反射技术的出现大大的提高了程序的扩展性。类不确定时都会用到反射技术。

Field field:将字段封装成对象类型 Field。
Constructor  cons ;将构造函数封装成了对象类型  Constructor。
Method  method ;将类中的成员都封装成了对象。
还提供了对这些成员的操作。
getField()
getContructor()

getMethod()


如何获取字节码文件 
要向获取字节码文件中的成员,必须要先获取字节码文件对象。
获取字节码文件的方式:
1、Object类中的getClass()方法,返回Object的运行时类。虽然通用,但是前提是必须有指定类,并对该类进行对象的创建,才可以调用getClass方法。
2、使用的任意数据类型的一个静态成员class,所有的数据类型都具备的一个属性。好处是不用new对象,但是,还需要使用具体的类。
3、使用Class类中能够的forName方法,通过给定的类名来获取对应的字节码文件对象。
只要知道类的名字就可以了,获取对应的字节码文件直接有forName方法自动完成。这就是反射技术使用的获取字节码文件对象的方式。Class.forName(className);自动去找寻该class文件,并加载进内存。
通过newInstance()就可以创建字节码对象所表示的类的实例。


Class  clazz = Class.forName(className);
//通过给定的类名称,加载对应的字节码文件,并封装成字节码文件对象Class
Object obj = clazz.newInstance(); 
//2、通过new创建给定类的实例。
//3、调用该类的构造函数。

//通过配置文件,就可以动态加载类,并创建其对象。


public class Reflect_GetClass {public static void main(String[] args)  throws ClassNotFoundException,InstantiationException,IllegalAccessException{//getClass_1();//getClass_2();getClass_3();}public static void getClass_1() {Person p = new Person();Class clazz = p.getClass();System.out.println(clazz);}public static void getClass_2() { Class clazz = Person.class;System.out.println(clazz.getName());}public static void getClass_3() throws ClassNotFoundException,InstantiationException,IllegalAccessException {String classname = "Person"; //类名为字符串,加上包名,写全部名称Class clazz = Class.forName(classname);/***相当于 Person obj = new Person();*   1、加载Person类,并Person类封装成字节码文件对象。*2、通过new创建Person对象。*   3、调用对象函数对对象进行初始化。*/Object obj = clazz.newInstance(); System.out.println(obj);} }


通常被反射的类都会提供空参数的构造函数。
ClassNotFoundException:类不能被找到
InstantiationException:  没有对应的构造函数
IllegalAccessException:如果有提供,但是权限不够。


如果要通过指定的构造函数初始化对象:
1、获取字节码文件对象。
2、再获取给定的构造函数。
3、通过构造函数初始化对象。


import java.lang.reflect.*; public class Reflect_GetConstructor{public static void main(String[] args)  throws Exception{getConstructor();}public static void getConstructor() throws Exception {String classname = "Person"; Class clazz = Class.forName(classname);//获取指定的构造器,获取Person类中的含有string和int的构造函数。Constructor con=clazz.getConstructor(String.class,int.class);//有了构造器后,通过构造器对象来初始化该类对象。newInstance方法为Constructor类中的方法。Object obj = con.newInstance("lisi",23);System.out.println(obj);} }

获取字段对象
        String fieldname = "age";
        //获取的是公共的字段
        //getxxx:获取的都是类中公共的字段
        //getDeclaredxxx:获取本类中能够已有的成员。
      

        Field field = clazz.getField(fieldname);
        Field field = clazz.getDeclaredField(fieldname);
        //通过查找父类AccessibleObject的setAccessible(true)方法,可以对任何字段更改。
        field.setAccessible(true);//取消权限检查,即暴力访问。一般不访问私有。
        

field.set(obj, 30);//age字段是私有的,如只有这一行会抛异常。
        System.out.println(field.get(obj));

0 0