Java类加载过程是java开发者需要掌握的基本知识,今天作总结:
1. 静态代码块与非静态代码块加载顺序
package com.apebug.entity;
public class Father {
{
System.out.println("父类 非静态代码块a");
}
static {
System.out.println("父类 静态代码块");
}
{
System.out.println("父类 非静态代码块b");
}
}
入口
public class DemoMain {
public static void main(String[] args){
Father father = new Father();
}
}
运行结果
父类 静态代码块
父类 非静态代码块a
父类 非静态代码块b
结论:静态代码块 > 非静态代码块 (非静态代码块按在类中出现的先成顺序依次执行)
2.非静态代码块与构造函数
这是一个很容易遗漏的一个对比,类加载完成后最先执行静态代码块,这一点大多人清楚,那非静态代码块与构造函数的顺序呢?我们把构造函数放在两个非静态代码块的中间,看看结果
package com.apebug.entity;
public class Father {
{
System.out.println("父类 非静态代码块a");
}
static {
System.out.println("父类 静态代码块");
}
public Father() {
System.out.println("父类 构造函数");
}
{
System.out.println("父类 非静态代码块b");
}
}
运行结果
父类 静态代码块
父类 非静态代码块a
父类 非静态代码块b
父类 构造函数
可以看到:非静态代码块 > 构造函数 ,只有所有的非静态代码块都执行完了才会执行构造函数
这里提出一个疑问,非静态代码块可以理解为是附在构造函数的前面执行吗?如果是这样,那么每次构造对象,非静态代码块都是会执行的,为此,我们初始化两个对角
public class DemoMain {
public static void main(String[] args){
Father father = new Father();
Father father2 = new Father();
}
}
运行结果
父类 静态代码块
父类 非静态代码块a
父类 非静态代码块b
父类 构造函数
父类 非静态代码块a
父类 非静态代码块b
父类 构造函数
非静态代码块会在每次构造函数调用前执行
结论:非静态代码块 > 构造函数,并且非静态代码块会在每次调用构造函数之前调用3.父类与子类
java实例化子类时,必定会先实例化一个父类对象,实例父类后必定是先加载类的,如下实验
//父类
public class Father {
{
System.out.println("父类 非静态代码块a");
}
static {
System.out.println("父类 静态代码块");
}
public Father() {
System.out.println("父类 构造函数");
}
{
System.out.println("父类 非静态代码块b");
}
}
//子类
public class Son extends Father{
{
System.out.println("子类代码块a");
}
static {
System.out.println("子类静代码块");
}
public Son() {
System.out.println("子类 构造函数");
}
{
System.out.println("子类代码块b");
}
}
//入口
public class DemoMain {
public static void main(String[] args){
Son son = new Son();
Son son2 = new Son();
}
}
结果:
父类 静态代码块
子类静代码块
父类 非静态代码块a
父类 非静态代码块b
父类 构造函数
子类代码块a
子类代码块b
子类 构造函数
父类 非静态代码块a
父类 非静态代码块b
父类 构造函数
子类代码块a
子类代码块b
子类 构造函数
可以看到,只有父类子类都加载完了才会实例化对象,类只需装载一次,当子类发现有父类时,会先装载父类,并执行完父类的静态代码块,再继续装载子类,装载完后执行子类静态代码块,再进行实例代过程,实例化过程中,有父类的,需先实例父类对象。
评论列表