类的加载 反射总结

        当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

  • 加载

        就是指将class文件读入内存,并为之创建一个Class对象。 任何类被使用时系统都会建立一个Class对象。

  • 连接

        验证:是否有正确的内部结构,并和其他类协调一致. 确保Class文件中包含的信息符合当前虚拟机的要求.比如,校验某非抽象类是否实现了抽象父类的全部方法.方法体中 类型转换 符号是否有效等.

        准备:负责为类的静态成员分配内存,并设置默认初始化值.

        解析:将类的二进制数据中的符号引用替换为直接引用.

  • 初始化

        对类的静态内容执行初始化操作

  • 类的加载时机

        1. 创建类的实例

        2. 类的静态变量,或者为静态变量赋值

        3. 类的静态方法

        4. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

        5. 初始化某个类的子类

        6. 直接使用java.exe命令来运行某个主类 main()

        到目前为止我们已经知道把class文件加载到内存做了哪些事情了,那么,如果我们仅仅站在这些class文件的角度,我们如何来使用这些class文件中的内容呢?那就是我们反射将要学习的内容了。

  • 反射概述

        Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

        简而言之,反射就是:在运行时通过代码操作Class,从而可以获取类中的字段,构造,方法等

        要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖这个类,使用的就是Class类中的方法,所以先要获取到每一个字节码文件所对应的Class类型对象。

  • Class的三种获取方式

        //1 通过类型获得

        // 语法:类名.class

        // 应用场景:确定类型等

        Class clazz1 = Bean.class;

        //2 通过实例对象获得

        // 语法:变量.getClass()

        // 应用场景:在方法内部通过参数获得类型等

        Bean bean = newBean();

        Class clazz2 = bean.getClass();

        //3 通过字符串获得

        // 语法:Class.forName("全限定类名")

        // 应用场景:通过配置获得字符串等

        Class clazz3 = Class.forName("com.rf.Bean");

  • 获取使用方法字段等

    //1获得构造-- 没有形参

    Constructor    constructor = beanClass.getConstructor();

    //2实例对象,没有实参

    Object    bean = constructor.newInstance();

    //1获得构造-- 两个字符串形参 -- Bean(String id, String className)

    Constructor    constructor = beanClass.getConstructor(String.class,String.class);

    //2 实例对象,两个字符串实参

    Object    bean = constructor.newInstance("ArrayListId","java.util.ArrayList");

  • 获取私有(暴力反射)

     getConstructor() 使用该方法将无法获得私有方法,程序运行抛异常

私有的属性方法都需要设置bean.setAccessible(true);

猜你喜欢

转载自blog.csdn.net/wzc1991520/article/details/80225213