Java类加载顺序

1、有继承关系的加载顺序

关于关键字static,大家 都知道它是静态的,相当于一个全局变量,也就是这个属性或者方法是可以通过类来访问,当class文件被加载进内存,开始初始化的时候,被static修饰的变量或者方法即被分配了内存,而其他变量是在对象被创建后,才被分配了内存的。

所以在类中,加载顺序为:

1.首先加载父类的静态字段或者静态语句块

2.子类的静态字段或静态语句块

3.父类普通变量以及语句块

4.父类构造方法被加载

5.子类变量或者语句块被加载

6.子类构造方法被加载

父类代码:

public class FuLei {
static int num  = 5;//1.首先被加载
static{
    System.out.println("静态语句块已经被加载"+num); //2.被加载
}
int count = 0; //5.被加载
{
    System.out.println("普通语句块"+count++);//6.被加载
}
public FuLei(){
    System.out.println("父类的构造方法在这时候加载count="+count);//7.被加载
}
}

子类代码:

public class ZiLei extends FuLei {
static{
    System.out.println("静态语句块和静态变量被初始化的顺序与代码先后顺序有关"); //3.被加载
}
static int num = 45;//4.被加载
int numre = 0; //8.被加载
{
    numre++;
    System.out.println("numre"+numre);//9.被加载

}
public ZiLei(){
    System.out.println("子类构造方法");//10.被加载
}
public static void main(String[] args){
    ZiLei ht = new ZiLei();
}
}

console打印:

静态语句块已经被加载5
静态语句块和静态变量被初始化的顺序与代码先后顺序有关
普通语句块0
父类的构造方法在这时候加载count=1
numre1
子类构造方法

注意

当class文件被加载进内存,开始初始化的时候,被static修饰的变量或者方法即被分配了内存,而其他变量是在对象被创建后,才被分配了内存的。

将子类代码中的创建对象注释掉

// ZiLei ht = new ZiLei();

console打印:

静态语句块已经被加载5
静态语句块和静态变量被初始化的顺序与代码先后顺序有关

2、没有继承关系的加载顺序

代码示例

public class Test {
public static void main(String[] args) {
    new Test();                         //4.第四步,new一个类,但在new之前要处理匿名代码块
}

static int num = 4;                    //2.第二步,静态变量和静态代码块的加载顺序由编写先后决定

{
    num += 3;
    System.out.println("b");           //5.第五步,按照顺序加载匿名代码块,代码块中有打印
}

int a = 5;                             //6.第六步,按照顺序加载变量

{ // 成员变量第三个
    System.out.println("c");           //7.第七步,按照顺序打印c
}

Test() { // 类的构造函数,第四个加载
    System.out.println("d");           //8.第八步,最后加载构造函数,完成对象的建立
}

static {                              // 3.第三步,静态块,然后执行静态代码块,因为有输出,故打印a
    System.out.println("a");
}

static void run()                    // 静态方法,调用的时候才加载// 注意看,e没有加载
{
    System.out.println("e");
}
}

console打印:

a
b
c
d

3、注意

  • 静态代码块(只加载一次)
  • 构造方法(创建一个实例就加载一次)
  • 静态方法,调用的时候才会加载,不调用的时候不会加载
  • 静态语句块和静态变量被初始化的顺序与代码先后顺序有关
### Java JVM虚拟机运行机制 JVM(Java虚拟机)是一种虚拟化的计算机,允许在其上执行Java程序(以及其他由Java编译器编译成字节码的程序),提供了一种跨平台的执行环境,具备“一次编写,到处运行”的特性[^2]。 一个Java文件从编码完成到最终执行,一般主要包括编译和运行两个过程。编译是通过`javac`命令将Java文件编译成字节码,即`.class`文件;运行则是把编译生成的`.class`文件交给Java虚拟机(JVM)执行[^3]。 JVM的运行机制主要包括内存划分、类加载机制和垃圾回收机制等。内存划分是将内存分为不同的区域,如堆、栈、方法区等,不同区域有不同的作用。类加载机制负责将Java字节码文件加载到内存中,并转换成可执行的Java。垃圾回收机制则负责回收不再使用的内存空间,以提高内存的利用率[^2]。 ### Java类加载顺序 JVM的类加载机制基于类加载器的概念,并按照特定的顺序进行类加载类加载过程一般分为以下几个步骤: 1. **加载**:通过的全限定名来获取定义此的二进制字节流,将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,在内存中生成一个代表这个的`java.lang.Class`对象,作为方法区这个的各种数据的访问入口。 2. **验证**:确保被加载的的正确性,验证字节码文件的格式、语义等是否符合Java虚拟机规范。 3. **准备**:为的静态变量分配内存,并将其初始化为默认值。例如,`int`型的静态变量初始值为0。 4. **解析**:将常量池内的符号引用替换为直接引用的过程。符号引用是一种文本形式的引用,而直接引用是指向目标的指针、句柄或偏移量等。 5. **初始化**:执行构造器`<clinit>()`方法的过程。`<clinit>()`方法是由编译器自动收集中的所有变量的赋值动作和静态语句块(`static{}`块)中的语句合并产生的。 类加载器有不同的型,如启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用程序类加载器(Application ClassLoader)等,它们按照双亲委派模型进行类加载,即当一个类加载器收到类加载请求时,它首先会把这个请求委托给父类加载器去完成,只有当父类加载器无法完成加载请求时,子类加载器才会尝试自己去加载[^1]。 以下是一个简单的示例代码,展示类加载过程中静态变量和静态代码块的执行顺序: ```java class Parent { static { System.out.println("Parent static block"); } static int parentStaticVar = 10; } class Child extends Parent { static { System.out.println("Child static block"); } static int childStaticVar = 20; } public class ClassLoadingOrderExample { public static void main(String[] args) { System.out.println(Child.childStaticVar); } } ``` 在上述代码中,当执行`main`方法时,会触发`Child`的加载。由于`Child`继承自`Parent`,根据类加载顺序,会先加载`Parent`,执行`Parent`的静态代码块和静态变量初始化,然后加载`Child`,执行`Child`的静态代码块和静态变量初始化,最后输出`Child`的静态变量`childStaticVar`的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

漁陽

彼此共勉,砥砺前行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值