博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

反射

Posted on 2020-06-29 23:12  心默默言  阅读(129)  评论(0编辑  收藏  举报

1.反射技术应用场景和特点

反射技术:动态的获取指定类以及动态的调用类中的内容。

应用场景:现在开发了一个my app的应用程序,想对其中的功能进行扩展,那么怎么能让后期出现的类被写好的应用程序所使用呢?通常的做法是实现相应的接口,实现完接口之后呢?我们需要在my app的源代码中使用接口创造相关对象。然而,app一般不会提供给你源代码,只是提供给你了.class文件,没法new 创建对象,这下怎么办呢?

 

2.字节码文件对应的类

 

3.获取字节码文件对象 

package cn.itcast.reflect.demo;

import cn.itcast.reflect.domain.Person;

public class Reflect_GetClassDemo {

    public static void main(String[] args) {
        /*
         * 要想获取字节码文件中的成员,要先获取字节码文件对象。 获取字节码文件对象方式: 
         * 1.通过object类中的getClass方法。
         * 虽然通用,但是前提必须要指定类,并对该类进行对象的创建,才可以调用getClass方法。
         *
         * 2.使用的是任意数据类型的静态成员class,所有数据类型都具备的一个属性。
         * 好处:不用new对象,但是,还需要使用具体的类。
         *
         * 3.使用class类中的forName方法,通过给定类名获取对应的字节码文件对象。
         * 这种方式很爽,只要知道类的名字就可以了,获取对应的字节码文件由forName方法自动完成。
         * 这就是反射技术使用的获取字节码文件对象的方式。
         *
         */
        getClass_1();
        getClass_2();
        getClass_3();

    }

    private static void getClass_3()  {
        // TODO Auto-generated method stub
        String calssName ="cn.itcast.reflect.domain.Person";
        try {
            Class clazz = Class.forName(calssName);
            System.out.println(clazz.getName());
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static void getClass_2() {
        // TODO Auto-generated method stub
        Class clazz = Person.class;
        System.out.println(clazz.getName()); // cn.itcast.reflect.domain.Person
    }

    private static void getClass_1() {
        // TODO Auto-generated method stub
        Person p1 = new Person();
        Person p2 = new Person();
        Class clazz1 = p1.getClass();
        Class clazz2 = p2.getClass();
        System.out.println(clazz1.getName()); // cn.itcast.reflect.domain.Person
        System.out.println(clazz1 == clazz2); // true
    }

}

4.动态创建字节码对象所表示的类的对象

package cn.itcast.reflect.demo;

import cn.itcast.reflect.domain.Person;

public class Reflect_GetClassDemo {

    public static void main(String[] args) throws Exception {

        getClass_3();

    }

    private static void getClass_3() throws ClassNotFoundException, InstantiationException, IllegalAccessException   {
        // TODO Auto-generated method stub
        String calssName = "cn.itcast.reflect.domain.Person";
        Class clazz = Class.forName(calssName);
        System.out.println(clazz.getName());
        // 通过newInstance()就可以创建字节码文件所表示的类的实例。
        Object obj = clazz.newInstance();
    }



}

5.常见的异常解析

package cn.itcast.reflect.demo;

public class Reflect_GetClassDemo {

    public static void main(String[] args) throws Exception {
        
        getClass_3();
        
    }

    private static void getClass_3() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        // TODO Auto-generated method stub
        String calssName = "cn.itcast.reflect.domain.Person";
        Class clazz = Class.forName(calssName);
//        System.out.println(clazz.getName());
        // 通过newInstance()就可以创建字节码文件所表示的类的实例。
        // 通常被反射的类都提供空参数的构造函数,如果没有对应的构造函数,会报InstantiationException
        // 如果有提供,但是权限不够,会报IllegalAccessException
        Object obj = clazz.newInstance(); 
    }

}

6.通过给定的构造函数进行实例化

package cn.itcast.reflect.domain;

public class Person {
    private String name;
    private int age;

    public Person() {
        // TODO Auto-generated constructor stub
        System.out.println("person run");
    }

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

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}
package cn.itcast.reflect.demo;

import java.lang.reflect.Constructor;

public class Reflect_GetConstructor {
    public static void main(String[] args) throws Exception {
        /*
         * 如果要通过指定的构造函数初始化对象怎么办呢?
         * 思路:
         * 1.获取字节码文件对象;
         * 2.在获取给定的构造函数;
         * 3.通过该构造函数初始化对象。
         */
        getConstructorDemo();
    }

    public static void getConstructorDemo() throws Exception {
        // TODO Auto-generated method stub
        String className = "cn.itcast.reflect.domain.Person";
        Class clazz = Class.forName(className);
        
        //获取指定的构造器,获取Person类中带参数的Sting,int构造函数
        Constructor cons = clazz.getConstructor(String.class,int.class);
        //有了构造对象后,通过构造器对象来初始化该类对象
        Object obj = cons.newInstance("lisi",21);
        System.out.println(obj);
    }
    
    
}

7.获取字段与暴力访问

package cn.itcast.reflect.demo;

import java.lang.reflect.Field;

public class Reflect_GetField {
    public static void main(String[] args) throws Exception {
        /*
         * 获取字段
         */
        getFieldDemo();
    }

    public static void getFieldDemo() throws Exception {
        // TODO Auto-generated method stub
        String className = "cn.itcast.reflect.domain.Person";
        Class clazz = Class.forName(className);
        
        String fieldName = "age"; 
        //获取字段
//        Field field = clazz.getField(fieldName);//获取的是公有的字段
        Field declaredField = clazz.getDeclaredField(fieldName);
        System.out.println(declaredField);
        
        //对其进行值的设置,必须先有对象
        Object obj = clazz.newInstance();
//        declaredField.set(obj, 30); //IllegalAccessException,age字段是私有的,不能直接修改
        declaredField.setAccessible(true);
        declaredField.set(obj, 30);
        
        System.out.println(declaredField.get(obj));//获取字段的值
        
    }
}
package cn.itcast.reflect.domain;

public class Person {
    public String name;
    private int age;

    public Person() {
        // TODO Auto-generated constructor stub
        System.out.println("person run");
    }

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

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}

8.获取方法

package cn.itcast.reflect.domain;

public class Person {
    public String name;
    private int age;

    public Person() {
        // TODO Auto-generated constructor stub
        System.out.println("person run");
    }

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

    public void show(String name, int age) {
        System.out.println("show run... name =" + name + ",age=" + age);
    }

    public static void staticShow() {
        System.out.println("staticShow run...");
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}
package cn.itcast.reflect.demo;

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

public class Reflect_GetMethodDemo {
    public static void main(String[] args) throws Exception {
        /*
         * 获取方法
         */
        getMethodDemo();
    }

    public static void getMethodDemo() throws Exception {
        // TODO Auto-generated method stub
        String className = "cn.itcast.reflect.domain.Person";
        Class clazz = Class.forName(className);

        Object obj = clazz.newInstance();

        String methodName = "show";

        Method method = clazz.getMethod(methodName, String.class, int.class);
        method.invoke(obj, "wangcai", 20); // show run... name =wangcai,age=20

        // 获取静态方法
        String methodName2 = "staticShow";
        Method method2 = clazz.getMethod(methodName2, null);
        method2.invoke(null, null); // staticShow run...

    }
}