java反射机制

在jvm中,加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构,这个对象就像是一面镜子,透过这个镜子看到类的结构,所以我们形象的称之为:反射,总而言之,简单一句话:反射就是将类的各个组成部分封装成为其他对象,这就是反射机制
**Reflection(反射)**是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API 取得任何类的内部信息,并能操作任意对象的内部属性及方法

在这里插入图片描述
反射相关的主要API

  • java.lang.Class:代表一个类,表示类的类,在原有普通类的基础上面更抽象了一层
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect.Field:代表类的成员变量
  • java.lang.reflect.Constructor:代表类的构造器
    java代码在计算机中存在有三个阶段
    在这里插入图片描述
    获取Class对象的方式:
  1. Class.forName(“全类名”):将字节吗文件加载进内存,返回Class对象
    ********多用于配置文件,将类名定义在配置文件中,读取文件,加载类
  2. 类名.class:通过类名的属性class获取 (此时已经加载进入了jvm,处于内存阶段)
    *******多用于参数的传递
  3. 对象.getClass(): getClass()方法在Object类中定义着。(此时已处于运行阶段)
    *****多用于对象的获取字节码方式
    通过代码演示获取Class对象的三种方式
    1.定义一个普通类
package reflect.pojo;
public class Person {
    private String name;
    private int id;

    public String a;
    protected String b;
     String c;
    private String d;
     public void eat(){
         System.out.println("eat.....");
     }

    public void eat(String food){
        System.out.println("eat"+food);
    }
    public Person(String name, int id) {
        this.name = name;
        this.id = id;
    }
    public Person() {
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }
}

2.编写测试类

package reflect;
import reflect.pojo.Person;
public class ReflectDemo01 {
    /**
     *  获取class对象的方式
     *    1.Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
     *    2.类名.class: 通过类名的属性class获取
     *    3.对象.getClass(): 该方法在Object类中定义着
     *  
     */
    public static void main(String[] args) throws Exception {
        // 1.Class.forName("全类名")    
        Class cls1 = Class.forName("reflect.pojo.Person");
        System.out.println(cls1);

          // 2.类名.class
        Class cls2 = Person.class;
        System.out.println(cls2);
           // 3. 对象.getClass()
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3);
           // 比较三个对象
        System.out.println(cls1==cls2); //true
        System.out.println(cls1==cls3); // true
    }  
}

得出结论:
同一个字节码文件(*.class)再一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个


**Class对象功能:

public class ReflectDemo2 {
    /**
     *   Class对象功能:
     *      *获取功能:
     *      1.获取成员变量们
     *          * Field[] getFields()
     *          * Field getField(String name)
     *
     *          *Field[] getDeclareFields() 获取所有的成员变量,不考虑修饰符
     *          * Field getDeclareField(String name)
     *       2. 获取构造方法们
     *            *Constructor<?> getConstructors()
     *            *Constructor<?> getConstructors(类<?>...parameterTypes)
     *
     *            *Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
     *            *Constructor<?>[] getDeclareConstructors()
     *
     *       3.获取成员方法们
     *           * Method[] getMethods()
     *           * Method getMethod(String name,类<?>... parameterTypes)
     *
     *           * Method[] getDeclareMethods()
     *           * Method getDeclareMethod(String name,类<?>..parameterTypes)
     *
     *       4. 获取类名
     *           * String getName()
     */
    public static void main(String[] args) throws Exception {

        Class personClass = Person.class;
        /**
         *
         * 1.获取成员变量们
         *     * Field[] getFields()
         *     * Field getField(String name)
         *
         *     *Field[] getDeclareFields()
         *     * Field getDeclareField(String name)
          */
            // 1.Field[] getFields()获取所有public修饰的成员变量
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("====================");
        Field a = personClass.getField("a");
           // 获取成员变量的值
        Person p = new Person();
        Object value = a.get(p);
        System.out.println(value);
            // 设置 a的值
         a.set(p,"张三");
        System.out.println(p);

        System.out.println("-------------------------------------");

            // Field[] getDeclareFields(): 获取所有的成员变量,不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
            //Field getDeclaredField(String name)
        Field d = personClass.getDeclaredField("a");
            // 忽略访问权限修饰符的安全检查
         d.setAccessible(true); // 暴力反射
        Object value2 = d.get(p);
        System.out.println(value2);
    }

}

获取构造方法们

public class ReflectDemo3 {
    /**
     *   Class对象功能:
     *      *获取功能:
     *      1.获取成员变量们
     *          * Field[] getFields()
     *          * Field getField(String name)
     *
     *          *Field[] getDeclareFields() 获取所有的成员变量,不考虑修饰符
     *          * Field getDeclareField(String name)
     *       2. 获取构造方法们
     *            *Constructor<?> getConstructors()
     *            *Constructor<?> getConstructor(类<?>...parameterTypes)
     *
     *            *Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
     *            *Constructor<?>[] getDeclareConstructors()
     *
     *       3.获取成员方法们
     *           * Method[] getMethods()
     *           * Method getMethod(String name,类<?>... parameterTypes)
     *
     *           * Method[] getDeclareMethods()
     *           * Method getDeclareMethod(String name,类<?>..parameterTypes)
     *
     *       4. 获取类名
     *           * String getName()
     */

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

             // 获取Person的class对象
        Class personClass = Person.class;

        /**
         *  获取构造方法们
         *    *Constructor<?> getConstructors()
         *    *Constructor<?> getConstructor(类<?>...parameterTypes)
         *    *Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
         *    *Constructor<?>[] getDeclareConstructors()
         *
          */
        Constructor constructor = personClass.getConstructor(String.class, int.class);
          System.out.println(constructor);
              // 创建对象
        Object person = constructor.newInstance("张三", 23);
          System.out.println(person);

        System.out.println("---------------");
        Constructor constructor1 = personClass.getConstructor();
        System.out.println(constructor1);
             // 创建对象
        Object person1 = constructor1.newInstance();
        System.out.println(person1);

            // 简化
        Object person3 = personClass.newInstance();
        System.out.println(person3);
    }
}

获取成员方法们

public class ReflectDemo4 {
    /**
     *   Class对象功能:
     *      *获取功能:
     *      1.获取成员变量们
     *          * Field[] getFields()
     *          * Field getField(String name)
     *
     *          *Field[] getDeclareFields() 获取所有的成员变量,不考虑修饰符
     *          * Field getDeclareField(String name)
     *       2. 获取构造方法们
     *            *Constructor<?> getConstructors()
     *            *Constructor<?> getConstructor(类<?>...parameterTypes)
     *
     *            *Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
     *            *Constructor<?>[] getDeclareConstructors()
     *
     *       3.获取成员方法们
     *           * Method[] getMethods()
     *           * Method getMethod(String name,类<?>... parameterTypes)
     *
     *           * Method[] getDeclareMethods()
     *           * Method getDeclareMethod(String name,类<?>..parameterTypes)
     *
     *       4. 获取类名
     *           * String getName()
     */

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

        // 获取Person的class对象
        Class personClass = Person.class;

        /**
         *  获取成员方法们
         *   * Method[] getMethods()
         *   * Method getMethod(String name,类<?>... parameterTypes)
         *   * Method[] getDeclareMethods()
         *   * Method getDeclareMethod(String name,类<?>..parameterTypes)
         */
             // 获取指定名称的方法
        Method eat_food = personClass.getMethod("eat");
        Person p = new Person();
            // 执行方法
        eat_food.invoke(p);

        Method eat_food2 = personClass.getMethod("eat", String.class);
            eat_food2.invoke(p,"饭");

        System.out.println("-------------------------");

          // 获取所有public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
                // 获取方法的名称
            System.out.println(method.getName());
            System.out.println(method);
        }
           // 获取类名
        String name = personClass.getName();
        System.out.println(name);
    }
}

反射的某种具体使用场景
在src目录下创建一个配置文件pro.properties,内容如下:
在这里插入图片描述
通过反射机制加载配置文件

/**
 * 假设这是一个框架类
 * 可以创建任意类的对象,执行任意方法
 */
public class ReflectTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        /**
         * 前提:不可以改变该类的代码, 可以创建任意类的对象,执行任意方法
         *
          */

          // 1. 加载配置文件
        // 1.1 创建Properties对象
        Properties pro = new Properties();
            // 1.2 加载配置文件,转换为一个集合
             // 1.2.1 获取class目录下的配置文件
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("pro.properties");
             pro.load(is);

              // 2. 获取配置文件中定义的数据
           String className = pro.getProperty("className");
           String methodName = pro.getProperty("methodName");


              //3. 加载该类进内存
           Class cls = Class.forName(className);
               // 4.创建对象
          Object obj = cls.newInstance();
                  // 5. 获取方法的对象
        Method method = cls.getMethod(methodName);
             // 6.执行方法
           method.invoke(obj);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值