类加载器+反射+动态代理
一. JVM和类
- 运行Java: java 带有main方法的类名
- 启动JVM,并加载字节码.
- 当调用java命令来运行某个Java程序时,该命令将会启动一个JVM进程.同一个JVM中的所有线程,变量都处于同一个进程中,共享该JVM的内存区域.当出现以下情况是,JVM会退出:
- 程序正常执行结束
- 使用System.exit(0)方法
- 出现异常时,没有捕获异常
- 平台强制结束JVM进程.
- JVM进程一旦结束,该进程中内存中的数据将会丢失.
二. 类的加载机制
当程序主动使用到某个类时,如果该类还未被加载进内存中,则系统会通过加载,连接,初始化三个步骤来对该类进行初始化操作.
类的加载
:
1. 类加载时指将类的class文件(字节码文件)载入内存中,并为之创建一个java.lang.Class对象,我们称之为字节码对象.
2. 类的加载过程由类加载器(ClassLoader)完成,类加载器通常由JVM提供,我们称之为系统类加载器,我们也可以继承ClassLoader类来提供自定义类加载器.
3. 不同的类加载器可以实现加载本地字节码文件,jar包中的字节码,通过网络加载字节码等.
- 类的连接
- 当类被加载进内存之后,系统为之生产一个对应的Class对象,接着把类的二进制数据合并到JRE(运行环境)中。
- 验证:检测被加载的类是否有正确的内部结构
- 准备:负责为类的static变量分配内存,并设置默认值
- 解析:把类的二进制数据中的符号引用替换为直接引用(书籍:深入分析JVM)
- 类的初始化
- 在此阶段,JVM负责对类进行初始化,主要就是对static变量进行初始化。只有主动使用类时才会执行初始化
类的初始化包含以下几个步骤:
- 如果该类还未被加载和连接,则程序先加载并连接该类.
- 如果该类的直接父类还未被初始化,则先初始化其父类,一直初始化类继承结构到Object
- 如果类中有初始化语句(静态代码块),则系统依次执行这些初始化语句.
三. 什么是反射
- 问题1
- 在面向对象中提到,一切事物都可以看成是对象,那么问题来了,类这种事物是啥对象呢?又使用什么类来表示类这种对象呢?
概念
:
- 元数据:数据的数据
- 反射:得到类的元数据的过程。在运行时期,动态去获取某一个类中的成员信息(构造器,方法,字段,内部类,接口,父类等等)。
我们把类中的每一种成员,都描述成一个新的类:
|类名|所在包|描述|
|—|—|—|
|Class| java.lang |表示所有的类|
|Constructor| java.lang.reflect |表示所有的构造器|
|Method| java.lang.reflect |表示所有的方法|
|Field| java.lang.reflect |表示所有的字段|
四. Class类
- Class类
- 用来描述类或者接口的类型,描述类的类.
- Class类的实例
- 在JVM中的一份份字节码,Class实例表示在JVM中的类或者接口,枚举是一种特殊的类,注解是一种特殊的接口.当程序第一次使用某一个java.util.Date类的时候,就会把该类的字节码对象加载进JVM,并创建出一个Class对象.此时的Class对象就表示java.util.Date的字节码.
- 如何创建Class对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14//方式一:使用class属性获取
Class c1 = Date.class;
//方式二:通过对象的getClass()方法获取,getClass()属于Object的方法
Date d = new Date();
Class c2 = d.getClass();
//方式三:通过Class中的forName方法获取【用的较多】
Class c3 = Class.forName("java.util.Date");
//打印输出
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
//同一个类在JVM中只存在一份字节码对象,下面的结果均为true
System.out.println(c1==c2);
System.out.println(c2==c3);
- 九大内置Class对象
- 在上述讲了三种获取Class对象的方式,基本数据类型不能表示为对象,也就不能使用getClass的方式,基本类型没有类名的概念,也不能使用Class.forName的方式,如何表示基本类型的字节码对象呢?所有的数据类型都有class属性。Class clz = 数据类型.class;
JVM中预先提供好的Class实例,分别:
byte,short,int,long,float,double,boolea,char,void.
byte.class,short.class,int.class,….void.class.
- 数组的Class对象
- 方式1: 数组类型.class;
方式2: 数组对象.getClass();
注意:所有的具有相同的维数和相同元素类型的数组共享同一份字节码对象,和元素没有关系
- 获取构造器
- public Constructor>[] getConstructors()
获取当前Class所表示类的所有的构造器,和访问权限无关