加深理解类的初始化顺序

前言

    Java虚拟机怎么加载类的成员,决定了我们书写代码的执行顺序。Python有模块的加载概念,其实任何编程语言,代码的加载顺序都存在,一起学习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 = ""

}

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

父、子类的加载情况

我们先写个父类

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会去执行一遍单个类的加载

总结

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

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

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

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

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值