类加载
过程
1、什么时机会触发某个类的加载(代码举例)?
a)构造该类的实例
b)调用该类的静态属性或方法
c)使用子类时会触发父类的加载
class AA{
public AA() {
System.out.println("AA的构造函数");
}
{
System.out.println("AA的代码块");
}
static {
System.out.println("AA的静态代码块");
}
}
class BB extends AA{
public BB() {
System.out.println("BB的构造函数");
}
{
System.out.println("BB的代码块");
}
static {
System.out.println("BB的静态代码块");
}
}
public class Demo extends BB {
public static void main(String[] args) {
System.out.println("开始");
new BB();
new BB();
System.out.println("结束");
}
}
AA的静态代码块
BB的静态代码块
开始
AA的代码块
AA的构造函数
BB的代码块
BB的构造函数
AA的代码块
AA的构造函数
BB的代码块
BB的构造函数
结束
总流程 加载AA->加载BB ->加载Demo ->执行main方法
Java类初始化顺序:父类静态变量–>父类静态代码块–>子类静态代码块–>父类非静态代码块–>父类构
造函数—子类非静态代变量–子类非静态代码块—>子类构造器
开始
AA的静态代码块
BB的静态代码块
AA的代码块
AA的构造函数
BB的代码块
BB的构造函数
AA的代码块
AA的构造函数
BB的代码块
BB的构造函数
结束
2、类加载器有哪些?
内置了三个类加载器
1. BootstrapClassLoader
加载标准库中的类. String, Arraylis…
2. ExternsionClassl oader
加载一个特殊目录中的类
3. ApplicationClassLoader
加载应用程序自己写的类
import sun.net.spi.nameservice.dns.DNSNameService;
public class Demo1 {
public static void main(String[] args) {
//应用程序自己写的类
ClassLoader classLoader = Demo1.class.getClassLoader();
System.out.println(classLoader);
System.out.println();
// 加载标准库中的类
ClassLoader classLoader1 = String.class.getClassLoader();
System.out.println(classLoader1);
System.out.println();
//加载一个特殊目录中的类
ClassLoader classLoader2 = DNSNameService.class.getClassLoader();
System.out.println(classLoader2);
}
}
sun.misc.Launcher$AppClassLoader@18b4aac2
null
sun.misc.Launcher$ExtClassLoader@677327b6
3、什么是双亲委派模型?
描述的是,类加载中,根据类名找类的.class文件的查找过程,属于文件解析中的一部分。
parent既可以表示父亲,也能表示母亲.有些资料.上直接翻译成"双亲"指的是双亲中的某一 个
总的来说就是当AppClassLoader拿到类,先依次向上上传,直到最高BootstrapClassLoader,先从Boots这个里面找,如果找不到再开始依次向下传递查找。
目的
尽量让标准库的类优先被加载.
例如你在代码中创建一个java.lang String这样的类,BootstrapClassLoader这个加载器是负责库中的类,所以先加载库中。名字和标准库的String类相同了,此时优先加载标准库的String
4、如果你自己写了一个类加载器,是否要遵守双亲委派?
可以违背.
只是标准库中的三个类加载器要遵守.其他的类加载器不太需要遵守.
Tomcat中的类加载器就没遵守. (要从webapps目录中加载指定的webapp的类
转载:https://blog.csdn.net/char_m/article/details/107742811