Javase类的加载和反射

一.类的加载  连接和初始化

   

    1.JVM和类

        当我们调用Java命令运行某个Java程序时, 该命令会启动一条Java虚拟机进程, 不管该Java程序有多复杂, 改程序启动了多少个线程, 它们都处于Java虚拟机进程里, 同一个JVM的所有线程, 所有变量都处于同一个进程里, 它们都使用该JVM进程的内存区. 当系统出现以下几种情况时, JVM进程将被终止:

        (1)程序运行到最后正常结束.

        (2)程序运行到使用System.exit()或Runtime.getRuntime().exit()代码结束程序.

        (3)程序执行过程中遇到未捕获的异常或者错误结束.

        (4)程序所在平台强制结束了JVM进程.

Javase类的加载和反射

Javase类的加载和反射

当第二个程序再次输出A类的静态属性时, 值为6, 因为运行TestA1和TEstA2是两次JVM进程, 第一个JVM进程运行结束之后, 它对A类所做的修改将全部丢失, 第二次运行JVM时将再次初始化A类. 两次运行Java程序处于两个不同的JVM进程里面, 两个JVM不会共享数据.

2.类的加载

    当程序主动使用某个类时, 如果该类还未被加载到内存中去, 系统会通过加载, 连接, 初始化三个步骤来对该类进行初始化, JVM会连续完成这三个步骤, 所以有时将这三步骤称为类加载或类初始化.

    类加载指的是将类的class文件读入内存中, 并为之创建一个java.lang.Class对象, 程序在使用任何类时, 系统都会为之建立一个java.lang.Class对象.    每个类是一批具有相同特征的对象的抽象. 而系统中所有的类,它们实际上也是对象, 它们都是java.lang.Class的实例.

    类的加载由类加载器完成, 类加载器通常由JVM提供, 这些类的加载器也是所有程序运行的基础, JVM提供的这些类加载器通常被称为系统类加载器, 开发者还可以通过继承ClassLoader基类来创建自己的类加载器.

3.类的连接

    当类被加载之后, 系统为之生成一个对应的Class对象, 接着将会进入连接阶段, 连接阶段将会负责把类的二进制数据合并到JRE中. 类的连接分为三个阶段:

        (1)验证: 验证阶段用于检验被加载的类是否具有正确的内部结构, 并和其他类协调一致.

        (2)准备: 类准备阶段则负责为类的静态属性分配内存, 并设置默认初始值.

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

4.类的初始化

      JVM初始化一个类包含如下几个步骤:

        (1)假如这个类还没有被加载和连接, 程序先加载并连接该类.

        (2)假如该类的直接父类还没有被初始化, 则先初始化其直接父类.

        (3)假如类中有初始化语句, 则系统依次执行这些初始化语句.

<***>当程序主动使用任何一个类时, 系统会保证该类以及所有父类(包括直接父类和间接父类)都会被初始化.

5.类初始化的时机

    当Java程序首次通过以下6种方式来使用某个类或接口时, 系统会初始化该类或接口:

    (1)创建类的实例, 为某个类创建实例的方式包括使用new关键字来创建实例, 通过反射来创建实例, 通过反序列化的方式来创建实例.

    (2)调用某个类的静态方法.

    (3)访问某个类或接口的静态属性, 或者为该静态属性赋值.

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

    (5)初始化某个类的子类, 该子类的所有父类都会被初始化.

    (6)直接使用java.exe命令来运行某个主类, 当运行某个主类时, 程序会先初始化该主类.

二. 类的反射

    1.什么是反射?

    反射就是通过获取class字节码文件对象/Class类对象, 来获取字节码文件对象中的成员变量, 构造方法, 和成员方法.

    Field: 简称成员变量    (Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。 反射的字段可能是一个类(静态)字段或实例字段。)

    Constructor:简称构造方法:提供关于类的单个构造方法的信息以及对它的访问权限.

    Method:简称成员方法:类或接口上单独某个方法(以及如何访问该方法)的信息.

    2.面试题: 如何获取class字节码文件对象/Class的类对象?

    三种方式:(1)Object中的getClass()方法

                  (2)某个类的静态class属性来获取该类的Class对象

                  (3)Class类中的方法:forName(String className)

                                              forName("类路径")该字符串的参数是某个类的全限定类名

    开发中使用第三种方式,forName方法中的参数是一个String类型,以后可以用字符串类型数据作为配置文件!

    3.通过Class对象获取构造方法并使用

    Javase类的加载和反射

Javase类的加载和反射   

Javase类的加载和反射

获取指定的构造方法

Javase类的加载和反射

获取私有的构造方法,并通过私有构造方法的对象来创建实例

Javase类的加载和反射

使用getDeclaredConstructor()方法同样可以获取其他访问权限的构造方法,并创建实例.

4.通过反射获取成员变量,并使用

Javase类的加载和反射

Javase类的加载和反射

5.通过反射获取成员方法,并使用

Javase类的加载和反射

    Javase类的加载和反射