java加深理解类的初始化顺序

部署运行你感兴趣的模型镜像

前言

    Java虚拟机怎么加载类的成员,决定了我们书写代码的执行顺序,一起学习Java中类的加载顺序,大概分为3种类型的加载

1、单个类的加载

2、父类、子类的加载

3、组合类的加载

    理解类的加载顺序,对阅读Java源码有极大的帮助,所以请一定好好学习

前置知识

1、静态成员

静态变量、静态代码块

2、实例成员

实例变量、普通代码块、构造方法

3、继承

4、对象的组合

5、类的加载

    这些是理解类加载机制的前置知识,不理解也没有关系,后续再去补充即可。本文将尽可能的带大家重温这些术语

单个类的加载情况

class Father {
    
    public static String name = "静态变量:wang";
    
    static {
         System.out.println(name);
         System.out.println("没啥,就是来玩的,static 代码块");
    }

    pubilc String age = "实例变量:age";

    {
         System.out.println(age);
         System.out.println("普通代码块");
    }

    public Father() {
         System.out.println("构造方法执行了");
    }

}

重温知识点(一个类由哪些部分组成)

静态变量:static修饰的变量

静态代码块:static {}

实例变量:没有static修饰的变量

普通代码块:{}

构造方法:类名(){}

上面这个类,包括静态变量、静态代码块、实例变量、普通代码块、构造方法,当我们首次使用这个类的时候,虚拟机会加载该Father类,我们一般这么用

Father first = new Father(); //创建一个Father对象

这个时候它的加载顺序如下,自上而下,有先后顺序

 

静态成员:静态变量、静态代码块

实例成员:实例变量、普通代码块、构造方法

类的静态成员优先加载、然后是实例成员的加载。我们再思考一个问题,同样的静态成员下,谁先加载呢?

相同成员,按照书写顺序加载

class Father {

    static {

          System.out.println("static代码块");

    }

    public static String name = ""

}

相同成员,谁书写在前面,谁就先加载,静态成员,实例成员都是如此的设计

public class MyClass {
    static {
        System.out.println("Static block 1");
    }
    
    static {
        System.out.println("Static block 2");
    }
    
    static int value = initValue();
    
    static {
        System.out.println("Static block 3");
    }
    
    private static int initValue() {
        System.out.println("Initializing value");
        return 10;
    }
    
    public static void main(String[] args) {
        System.out.println("Main method");
    }
}

输出(我度这个例子还挺好,可以看到静态变量最先被加载,接着按照静态代码块的顺序加载,静态代码块可以多个)

Initializing value
Static block 1
Static block 2
Static block 3
Main method

父、子类的加载情况

我们先写个父类

class Father{
     private static String name = "父类静态变量:name";

     static {
          System.out.println(name);
          System.out.println("父类静态代码块");
     }

     private String baby = "父类实例变量:baby";

     {
          System.out.println(baby);
          System.out.println("父类普通代码块");
     }


     public Father() {
          System.out.println("父类构造方法");
     }

}

再写个子类 

class Son extends Father {

       private static String nickName = "子类静态变量:nickName";

       static {
             System.out.println(nickName);
       }

       private String notBaby = "子类实例变量:notBaby";

       {
            System.out.println(notBaby);
            System.out.println("子类普通代码块");
       }

       public Son() {
             System.out.println("子类构造方法");
       }

}

什么是继承?

答:在java中,使用extends作为继承语法,子类会继承父类的属性和方法(私有也继承了,只不过通过子类对象访问不了)

new一个Son对象,看看此时的加载情况

Son mySon = new Son();

这个时候它的加载顺序如下,也是按照先后顺序进行加载的

组合类的加载

我们先写个要被使用的类

public class Tool {

    public Tool(){
        System.out.print("我是Tool的构造方法");
    }

    
    public void turnLight() {
        System.out.print("开灯");
    }

}

再写个Person,用于使用Tool

public class Person {
     
     private Tool tool = new Tool();
     
     public Person(){
         
     }

     public void change() {
            tool.turnLight();
     }

}

什么是组合?

答:当在一个对象中,持有另一个类的对象,我们称为组合,这也是最常见的复用代码的方式。

此时的加载流程如下

Person类先加载,接着就看我们组合类的使用为静态成员、还是实例成员,也是加载成员的时候,会去加载没有加载的类

Tool对象作为Person的实例成员,注意:Tool类必须是第一次使用,那么也会执行类的加载机制,类的加载机制只会执行一次

Person类加载过程中,由于Tool类没有加载,作为实例成员的Tool会去加载,此时的Tool会去执行一遍单个类的加载

关于静态组合时,使用静态成员的加载

public class Person {
     
     private static Tool tool = new Tool(); //Person类加载的时候,Tool类作为静态成员会优先加载完毕
     
     public Person(){
     }

     public void change() {
            tool.turnLight();
     }

}

总结

1、当一个类第一次使用,有且只会加载一次

2、静态成员优先加载、接下来是实例成员

3、相同级别成员,谁的书写顺序在前,谁就先加载

4、前置知识慢慢补吧,类的加载,有助于提高java代码的理解能力

您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值