< 笔记 > Java SE

来源:互联网 发布:代挂乐最新源码 编辑:程序博客网 时间:2024/05/29 09:30

09 Java SE 反射

By Kevin Song

定义:反射机制是在运行状态中,对于任意一个(class文件),都能知道这个类的所有方法属性。对于任意一个对象都能调用它的任意一个方法属性

Tomcat例

  • Tomcat App提供 Servlet接口
  • MyServlet类实现Servlet接口
  • 编写MyServlet类配置文件
  • Tomcat直接读取配置文件来动态获取MyServlet类中的方法和属性
    • Tomcat通过Class类来获取MyServlet类字节码文件中的内容(想要对MyServlet文件进行内容获取,第一步要获取该类的字节码文件对象即可)
      • 获取Class类中的对象(字节码文件对象)
        • Tomcat通过Class类中的forName()方法获取MyServlet类字节码文件对象
      • 获取Class类中的构造方法
        • 通过newInstance()获取该类空构造方法对象
        • 通过getConstructor获取构造方法对象
          • 再通过构造方法对象newInstance();方法来创建非空参对象
      • 获取Class类中的字段
      • 获取Class类中的方法
class Person {    name;    age;}Person p1 = new Person(Leo, 20);Person P2 = new Person(Kylo, 28);
//描述字节码文件的类class Class {    提供可以获取字节码文件的内容(字段,构造方法,一般方法)}class Demo {    int a = 6;    Demo() {}    void show() {}}class Test {    int b = 9;    Test() {}    void abc() {}}

获取Class对象

三种方式
- 方式三:Object类中的getClass()方法
- 必须明确具体的类并且创建对象
- 方式二:任何数据类型都具备一个静态的属性.class来获取其对应的class对象
- 要明确类中的静态成员
- 方式三:通过给定的类的字符串名称就可以获取该类
- Class类中的forName()方法

public class ReflectDemo {    public static void main(String[] args) {        //方式一:Object类中的getClass()方法        public static void getClassObject_1() {            Person p = new Person();            Class clazz = p.getClass();            Person p1 = ne Person();            Class clazz1 = p1.getClass();            System.out.println(clazz==clazz1);//true        }        //方式二        public static void getClassObject_2() {            Class clazz = Person.class;            Class clazz1 = Person.class;            System.out.println(clazz==clazz1);//true        }        //方式三        public static void getClassObject_3() throws ClassNotFoundException {            String className ="Person";            Class class = Class.forName(className);            System.out.println(clazz);        }    }}public class Person {    private int age;    private String name;    public Person(int age, String name) {        super();        this.age = age;        this.name = name;        System.out.println(personParam run"");    }    public Person() {        super;        System.out.println(person run"");    }    public void show() {        System.out.println(name+"..."+age);    }    private void method() {        System.out.println("method run");    }    public void paraMethod(String str, int num) {        System.out.println("paramMethod run"+str+":"+num);    }    public static void staticMethod() {        System.out.println("staticMethod run");    }}

获取Class中的构造方法

  • 早期创建对象
    • new的时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内创建该字节码文件对象,然后创建该字节文件的对应Person对象
  • 反射创建对象
    • 只要知道类名,通过Class来创建该类字节码文件对象
      • 通过newInstance()获取该类空构造方法对象
      • 通过getConstructor获取构造方法对象
        • 再通过构造方法对象newInstance();方法来创建非空参对象
public class ReflectDemo2 {    public static void main(String[] args) {        createNewObject_1();        createNewObject_2();    }    //空参数构造方法    public static void createNewObject_1() {        //以前        Person p = new Person();        //反射        String name = "Person";        Class clazz = Clazz.forName(name);//获取Person类字节码文件对象        Object obj = clazz.newInstance();//产生Person类对象    }    //非空参数构造方法    public static void createNewObject_2() {        String name = "Person";        Class clazz = Clazz.forName(name);//获取Person类字节码文件对象        //获取指定构造函数的对象        Constructor constructor = clazz.getConstructor(String.class, int.class);        Object obj = constructor.newInstance("Kylo", 29);    }}

获取Class中的字段

public class ReflectDemo3 {    public static void main(String[] args) {        createNewObject_1();        createNewObject_2();    }    //空参数构造方法    public static void getFieldDemo() {        Class clazz = Class.forName("Person");        Field field = clazz.getField("age");//获取公有的        field = clazz.getDeclaredField("age");//获取本类,包含私有        //对私有字段的访问取消权限检查,强制访问        field.setAccessible(true);        Object obj = clazz.newInstance();        field.set(obj,20);        Object o = field.get(obj);        System.out.println(o);    }}

获取Class中的方法

public class ReflectDemo4 {    public static void main(String[] args) throws Exception {        getMethodDemo_3();    }    //获取有参方法    public static void getMethodDemo_3() throws Exception {        Class clazz = Class.forName("cn.itcast.bean.Person");        Method method = clazz.getMethod("paramMethod", String.class,int.class);        Object obj = clazz.newInstance();        method.invoke(obj, "小强",89);    }    //获取无参方法    public static void getMethodDemo_2() throws Exception {        Class clazz = Class.forName("cn.itcast.bean.Person");        Method method = clazz.getMethod("show", null);//获取空参数一般方法。        //Object obj = clazz.newInstance();        Constructor constructor = clazz.getConstructor(String.class,int.class);        Object obj = constructor.newInstance("小明",37);        method.invoke(obj, null);    }    //获取指定Class中的所有公共方法    public static void getMethodDemo() throws Exception {        Class clazz = Class.forName("cn.itcast.bean.Person");        Method[] methods  = clazz.getMethods();//获取的都是公有的方法。         methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包含私有。         for(Method method : methods){            System.out.println(method);        }    }}

反射练习

public class Mainboard {    public void run() {        System.out.println("main board run....");    }    public void usePCI(PCI p) {//PCI p = new SouncCard();        if (p != null) {            p.open();            p.close();        }    }}public class SoundCard implements PCI {    public void open(){        System.out.println("sound open");    }    public void close(){        System.out.println("sound close");    }}public class NetCard implements PCI {    @Override    public void open() {        System.out.println("net open");    }    @Override    public void close() {        System.out.println("net close");    }}public interface PCI {    public void open();    public void close();}/* * 电脑运行。  */public class ReflectTest {    public static void main(String[] args) throws Exception {        Mainboard mb = new Mainboard();        mb.run();        //每次添加一个设备都需要修改代码传递一个新创建的对象        //mb.usePCI(new SoundCard());        //能不能不修改代码就可以完成这个动作。        //不用new来完成,而是只获取其class文件。在内部实现创建对象的动作。         File configFile = new File("pci.properties");        Properties prop = new Properties();        FileInputStream fis = new FileInputStream(configFile);        prop.load(fis);        for(int x=0; x<prop.size(); x++){            String pciName = prop.getProperty("pci"+(x+1));            Class clazz = Class.forName(pciName);//用Class去加载这个pci子类。            PCI p = (PCI)clazz.newInstance();            mb.usePCI(p);        }        fis.close();    }}pci.properties文件pci1=cn.itcast.reflect.test.SoundCardpci2=cn.itcast.reflect.test.NetCard
原创粉丝点击