18.1 类的加载 连接 初始化
    类的加载:加载 连接 初始化
    所有的类,都是一个java.lang.Class对象
    加载 读取.class文件,在内存中生成对应的Class文件
    连接
    初始化 静态变量和静态代码块的初始化
    JVM最先初始化的总是java.lang.Obeject对象
    类初始化的时机:
    6种
    特例:
    1、对于一个final型的静态类变量,如果该Field的值在编译时就可以确定下来,那么这个Field相当于宏变量,编译时直接替换,程序使用该静态Field也不会导致该类的初始化
    2、使用ClassLoader类的loadClass方法来加载某个类时,只是加载该类,并不会执行该类的初始化,使用Class的forName静态方法才会导致强制初始化该类
    18.2 类加载器
    JVM中同一个类只会被加载一此,那么如何区分不同的类呢?
    全限定类名+类加载器名
    当JVM启动时,会形成由3个类加载器组成的初始类加载器层次结构:
    Bootstrap ClassLoader根类加载器,负责加载Java的核心类;不是Java.lang.ClassLoader的子类,不是用Java实现的 rt.jar
    Extension ClassLoader 扩展类加载器,负责加载JRE的扩展目录(%JAVA_HOME%/jre/lib/ext或者java.ext.dirs)中JAR包的类; /lib/ext
    System ClassLoader 系统类加载器,负责在JVM启动时加载来自java命令-classpath选项、java.class.path系统属性,或CLASSPATH环境变量所指定的JAR包和类路径
    类加载机制:全盘负责、父类委托、缓存机制
    4种类型加载器的层次
    用户类加载器—》系统类加载器—》扩展类加载器—》根类加载器
    JVM中除根类加载器外的所有类加载器,都是ClassLoader的子类
    Class的缓存,如果已经加载了,缓存中存在,就不会再次加载
    18.3 通过反射查看类信息
    对象的编译时类型和运行时类型
    java.lang.Class 诸多方法
    获得Class对象:
    1、使用Class类的forName(String clazzName)静态方法;clazzName不需要提前确定
    2、调用某个类的class属性(Person.class);这种方式更安全,性能更好
    3、调用某个对象的getClass()方法,该方法继承自Object
    Class<?> getClass() 返回此 Object 的运行时类。
    从Class中获取信息:
    Class对象可以获取类中的方法Method、构造器Constructor、成员变量Field
    Field 成员变量
    要确定一个方法,需要由方法名和形参列表来确定,但是形参名没有任何意义,所以只能由形参类型来确定
    18.4 通过反射生成并操作对象
    Class对象可以获取类中的方法Method、构造器Constructor、成员变量Field
    通过反射来创建对象:
    1、使用Class对象的newInstance()方法来创建该Class对象对应的实例,
    这种方式要求该Class对象的对应类有默认构造器
    2、使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例
    方法可以指定某一特定构造函数来生成对象
    通过反射来调用方法:
    mtd.invoke(target , config.getProperty(name));
    通过Method的invoke方法来调用对应的方法时,Java会要求程序必须有调用该方法的权限。
    当确实需要调用某个对象的private方法,可以先调用setAccessible(boolean flag)取消访问权限检查。Method、Constructor和Field都可以调用该方法
    采用这种办法,即可通过反射访问到类的私有成员
    Spring架构:配置文件配置对象,由程序根据配置文件来创建对象
    通过反射来访问成员变量:
    通过反射来操作数组:
    通过Array开动态生成数组