Java 的类加载顺序

Posted 勇闯天涯zfc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 的类加载顺序相关的知识,希望对你有一定的参考价值。

 

Java 的类加载顺序

一、加载顺序

1、父类的静态成员变量初始化

  1.1、静态代码块

  1.2、普通代码块

  1.3、无参构造器

2、父类的静态代码块

3、子类的静态成员变量初始化

  3.1、静态代码块

  3.2、普通代码块

  3.3、无参构造器

4、子类的静态代码块

5、父类的普通成员变量初始化

  5.1、静态代码块

  5.2、普通代码块

  5.3、无参构造器

6、父类的普通代码块

7、父类的无参构造器

8、子类的普通成员变量

  8.1、静态代码块

  8.2、普通代码块

  8.3、无参构造器

9、子类的普通代码块

10、子类的无参构造器

二、示例代码

  超级父类A,父类B,子类C,B继承A,C继承B;

  AA、AAA、BB、BBB、CC、CCC都有各自的普通、静态成员变量,普通、静态代码块和无参构造器

  超级父类A的普通成员变量aa(AA类的实例),超级父类A的静态成员变量aaa(AAA类的实例);

  父类B的普通成员变量bb(BB类的实例),父类B的静态成员变量bbb(BBB类的实例);

  子类C的普通成员变量cc(CC类的实例),子类C的静态成员变量ccc(CCC类的实例);

1、超级父类A

 

package cn.com.zfc.lesson05.inherit01;

 

/**
*
* @title A
* @describe 超级父类 A
* @author 张富昌
* @date 2017年4月3日下午5:59:17
*/
public class A {

  //普通成员变量

 

  private AA aa = new AA();

  //静态成员变量
  private static AAA aaa = new AAA();

 

  // 静态代码块
  static {
    System.out.println("我是超级父类 A 的静态代码块");
  }

 

  // 普通代码块
  {
    System.out.println("我是超级父类 A 的普通代码块");
  }

 

  // 无参构造方法
  public A() {
    System.out.println("我是超级父类 A 的无参构造方法");
  }
}

 

2、父类B

 

package cn.com.zfc.lesson05.inherit01;

 

/**
*
* @title B
* @describe 父类
* @author 张富昌
* @date 2017年4月3日下午5:59:17
*/
public class B extends A {

  //普通成员变量
  private BB bb = new BB();

  //静态成员变量
  private static BBB bbb = new BBB();

 

  // 静态代码块
  static {
    System.out.println("我是父类 B 的静态代码块");
  }

 

  // 普通代码块
  {
    System.out.println("我是父类 B 的普通代码块");
  }

 

  // 无参构造方法
  public B() {
    System.out.println("我是父类 B 的无参构造方法");
  }
}

 

3、子类C

 

package cn.com.zfc.lesson05.inherit01;

 

/**
*
* @title C
* @describe 子类 C
* @author 张富昌
* @date 2017年4月3日下午5:59:17
*/
public class C extends B {

  //普通成员变量

  private CC cc = new CC();

  //静态成员变量
  private static CCC ccc = new CCC();


  // 静态代码块
  static {
    System.out.println("我是子类 C 的静态代码块");
  }

 

  // 普通代码块
  {
  System.out.println("我是子类 C 的普通代码块");
  }

 

  // 无参构造方法
  public C() {
    System.out.println("我是子类 C 的无参构造方法");
  }
}

 

4、AA类

 

package cn.com.zfc.lesson05.inherit01;

 

/**
*
* @title AA
* @describe 超级父类 A 的普通成员变量 AA
* @author 张富昌
* @date 2017年4月3日下午5:59:17
*/
public class AA {
  // 静态代码块
  static {
    System.out.println("我是超级父类 A 的普通成员变量 AA 的静态代码块");
  }

 

  // 普通代码块
  {
    System.out.println("我是超级父类 A 的普通成员变量 AA 的普通代码块");
  }

 

  // 无参构造方法
  public AA() {
    System.out.println("我是超级父类 A 的普通成员变量 AA 的无参构造方法");
  }
}

 

5、AAA类

 

package cn.com.zfc.lesson05.inherit01;

 

/**
*
* @title AAA
* @describe 超级父类 A 的静态成员变量 AAA
* @author 张富昌
* @date 2017年4月3日下午5:59:17
*/
public class AAA {
  // 静态代码块
  static {
    System.out.println("我是超级父类 A 的静态成员变量 AAA 的静态代码块");
  }

 

  // 普通代码块
  {
    System.out.println("我是超级父类 A 的静态成员变量 AAA 的普通代码块");
  }

 

  // 无参构造方法
  public AAA() {
    System.out.println("我是超级父类 A 的静态成员变量 AAA 的无参构造方法");
  }
}

 

6、BB类

 

package cn.com.zfc.lesson05.inherit01;

 

/**
*
* @title BB
* @describe 父类 B 的普通成员变量 BB
* @author 张富昌
* @date 2017年4月3日下午5:59:17
*/
public class BB {
  // 静态代码块
  static {
    System.out.println("我是父类 B 的普通成员变量 BB 的静态代码块");
  }

 

  // 普通代码块
  {
    System.out.println("我是父类 B 的普通成员变量 BB 的普通代码块");
  }

 

  // 无参构造方法
  public BB() {
    System.out.println("我是父类 B 的普通成员变量 BB 的无参构造方法");
  }
}

 

7、BBB类

 

package cn.com.zfc.lesson05.inherit01;

 

/**
*
* @title BBB
* @describe 父类 B 的静态成员变量 BBB
* @author 张富昌
* @date 2017年4月3日下午5:59:17
*/
public class BBB {
  // 静态代码块
  static {
    System.out.println("我是父类 B 的静态成员变量 BBB 的静态代码块");
  }

 

  // 普通代码块
  {
    System.out.println("我是父类 B 的静态成员变量 BBB 的普通代码块");
  }

 

  // 无参构造方法
  public BBB() {
    System.out.println("我是父类 B 的静态成员变量 BBB 的无参构造方法");
  }
}

 

8、CC类

 

package cn.com.zfc.lesson05.inherit01;

 

/**
*
* @title CC
* @describe 子类 C 的普通成员变量 CC
* @author 张富昌
* @date 2017年4月3日下午5:59:17
*/
public class CC {
  // 静态代码块
  static {
    System.out.println("我是子类 C 的普通成员变量 CC 的静态代码块");
  }

 

  // 普通代码块
  {
    System.out.println("我是子类 C 的普通成员变量 CC 的普通代码块");
  }

 

  // 无参构造方法
  public CC() {
    System.out.println("我是子类 C 的普通成员变量 CC 的无参构造方法");
  }
}

 

9、CCC类

 

package cn.com.zfc.lesson05.inherit01;

 

/**
*
* @title CCC
* @describe 子类 C 的静态成员变量 CCC
* @author 张富昌
* @date 2017年4月3日下午5:59:17
*/
public class CCC {
  // 静态代码块
  static {
    System.out.println("我是子类 C 的静态成员变量 CCC 的静态代码块");
  }

 

  // 普通代码块
  {
    System.out.println("我是子类 C 的静态成员变量 CCC 的普通代码块");
  }

 

  // 无参构造方法
  public CCC() {
    System.out.println("我是子类 C 的静态成员变量 CCC 的无参构造方法");
  }
}

10、测试子类C的创建过程:TestC.java

package cn.com.zfc.lesson05.inherit01;
/**
*
* @title TestC
* @describe 测试子类C的创建过程
* @author 张富昌
* @date 2017年4月3日下午6:49:50
*/
public class TestC {
  public static void main(String[] args) {

    //创建 C 对象
    C c = new C();
  }
}

三、测试结果

 

我是超级父类 A 的静态成员变量 AAA 的静态代码块
我是超级父类 A 的静态成员变量 AAA 的普通代码块
我是超级父类 A 的静态成员变量 AAA 的无参构造方法
我是超级父类 A 的静态代码块
我是父类 B 的静态成员变量 BBB 的静态代码块
我是父类 B 的静态成员变量 BBB 的普通代码块
我是父类 B 的静态成员变量 BBB 的无参构造方法
我是父类 B 的静态代码块
我是子类 C 的静态成员变量 CCC 的静态代码块
我是子类 C 的静态成员变量 CCC 的普通代码块
我是子类 C 的静态成员变量 CCC 的无参构造方法
我是子类 C 的静态代码块
我是超级父类 A 的普通成员变量 AA 的静态代码块
我是超级父类 A 的普通成员变量 AA 的普通代码块
我是超级父类 A 的普通成员变量 AA 的无参构造方法
我是超级父类 A 的普通代码块
我是超级父类 A 的无参构造方法
我是父类 B 的普通成员变量 BB 的静态代码块
我是父类 B 的普通成员变量 BB 的普通代码块
我是父类 B 的普通成员变量 BB 的无参构造方法
我是父类 B 的普通代码块
我是父类 B 的无参构造方法
我是子类 C 的普通成员变量 CC 的静态代码块
我是子类 C 的普通成员变量 CC 的普通代码块
我是子类 C 的普通成员变量 CC 的无参构造方法
我是子类 C 的普通代码块
我是子类 C 的无参构造方法

 

 

总结:

  第一点,所有的类都会优先加载基类
  第二点,静态成员的初始化优先
  第三点,成员初始化后,才会执行构造方法
  第四点,静态成员的初始化与静态块的执行,发生在类加载的时候。
  第四点,类对象的创建以及静态块的访问,都会触发类的加载。















































































































































































































以上是关于Java 的类加载顺序的主要内容,如果未能解决你的问题,请参考以下文章

java中类的加载顺序介绍(ClassLoader)

Tomcat中jar包和class的加载顺序

一次性搞清Java中的类加载问题

JVM笔记:Java虚拟机的类加载机制

类装载机制的类的初始化顺序

java第五章:面向对象(oop)之 static关键字