java中的类加载有三个阶段
- 加载
- 链接
- 验证
- 准备
- 解析
- 初始化
类整个从加载入内存到卸载出内存有7个步骤
增加了
- 使用
- 卸载
加载阶段是由类加载器完成的,类加载器有三类
- BootStrap
- BootStrap是最基础的类加载器
- 大部分是由c写的,其它类加载器都是java.lang.ClassLoader实现的
- 加载的目录 JRE/lib/rt.jar
- Extension
- Extension是BootStrap的子类加载器
- 加载的目录 JRE/lib/ext
- Application/System
- Application是Extension的子类加载器
- 加载的目录是classpath所定义的目录
- 自定义的类加载器都是Application类加载器的子类
- 这是默认的类加载器
类加载器有三个机制,可以保证类只会被加载一次
- 双亲委托
- 当子类加载器需要加载一个类,会委托父类加载器检查是否已经加载了此类,如果已经加载,那么无需加载;如果没有加载那么自身就会加载此类
- 可见性
- 子类加载器看得到父类加载器所加载的类,而父类加载器无法看到子类加载器所加载的类
- 单一性
- 每个类只会被加载一次
- 单一性其实就是委托机制所推得的
假如现在需要加载一个类 Test.class
- 首先Application类加载器会将加载需求告诉Extension类加载器(双亲委托)
(?为什么是先调用Application类加载器:这是默认的类加载器) - Extensin类加载器会将需求告诉BootStrap类加载器(双亲委托)
- BootStrap已经没有父类加载器,所以会查看 JRE/lib/rt.jar 中是否有此类,如果有,便加载
- 如果没有,Extension类加载器会查看 JRE/lib/ext目录中是否存在此类,如果有,便加载
- 如果没有,Application类加载器会查看classpath所定义的路径中是否有此类,有,便加载
类加载的时候是惰性的, 不会全都一下加载好,而是碰到用到这个类的时候才会去加载这个类。
比如A 类中用到了B类,那么只会在运行到这一行的时候才会去加载这个类
类中有静态域,构造块以及构造函数
静态域是和类有关的,静态域总的来说分飞静态代码块和静态变量,这些都是在类加载的时候就初始化好了。并且只会初始化一次。所以说静态块只会执行一次。,如果静态域中有多个元素,那么按照顺序初始化。
构造块就是写在类中的,用{}包括起来的语句。可以初始化对象的成员变量;执行的时候,构造块是比类构造函数更早执行的,而且每次创建一个对象的时候都会调用一次。
构造函数也是用来初始化对象的属性的。在重载了默认的构造函数之后,默认的构造函数就会消失;假如重载了构造函数,并且是带参数的,那么建议自己再写一个空的构造函数,防止子类在创建对象的时候报错
class A{
public A(int a){
}
}
class B extends A{
public static void main(String[] args){
B b = new B();
}
}
上述会报错,因为创建子类对象的时候,需要先调用父类的构造器,这样父类的构造器需要参数,那么就会报错,所以一般来说,重载构造方法之后还会加一个空的构造方法。
class A{
public A(int a){
}
public A(){
}
}
class B extends A{
public static void main(String[] args){
B b = new B();
}
}
构造块和构造方法中还可以初始化final常量的值,final常量除了在声明的时候就定义好,还可以在这两个地方定义
static中也可以初始化,不过需要final常量是类变量,也就是static修饰的。