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 的无参构造方法

总结:

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

时间: 2024-10-23 17:47:13

Java 的类加载顺序的相关文章

Java虚拟机类加载顺序

Java虚拟机在加载类的时候,先初始化父类静态变量,再初始化子类静态变量,然后加载父类,最后加载子类 public class Parent { static{ System.out.println("static parent"); } public Parent(){ System.out.println("parent loaded"); } public void getaaa(){ System.out.println("parent aaa&q

java中类加载顺序

引子 记得上次中秋一哥们写个需求,没写完.他中秋过后还请一天假,有点错,打电话叫我帮他继续搞. 由于测试支撑,叫到我加班了.第二天过来看,打开页面直接报错,再次点击报错就不一样了.前次报错是有代码行的,第二次直接页面说类发现什么的错. 看了下代码,类似如下: 1 package san; 2 3 import java.io.FileNotFoundException; 4 import java.util.logging.Level; 5 import java.util.logging.Lo

java 继承类加载顺序

package xu.jin; class Insect{ private int i=print("hello i"); Insect(){System.out.println("Insect"+i);} { System.out.println("1"); System.out.println("2"); } static{ System.out.println("3"); System.out.pri

分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码

先回顾一下classpath classpath的作用: classpath的作用是指定查找类的路径:当使用java命令执行一个类(类中的main方法)时,会从classpath中进行查找这个类. 指定classpath的方式一:         设置环境变量CLASSPATH,多个路径之间使用英文的分号隔开,也可以指定为jar包路径.          示例:CLASSPATH=c:/myclasses/;c/mylib/aa.jar;c:/mylib/bb.jar;.          注意

扩展类加载器-------改变JAVA的父优先类加载顺序

java的类加载机制默认情况下是采用委托模型:当加载某个类时JVM会首先尝试用当前类加载器的父类加载器加载该类,若父类加载器加载不到再由当前类加载器来加载,因此这种模型又叫做"父优先"模型. 但是在实际项目中我们可能会要求先从当前类加载加载再从父类加载器加载,如项目中的某类的版本可能和container中的不一致的时候,若还从container加载就会报jar包冲突的异常,实际上jar包冲突的问题在实际开发过程中是经常会遇到的.如我们在开发Loong时就遇到了类似问题. 解决方案是通过

Java 对象初始化顺序 执行顺序

先看一道Java面试题: 求这段程序的输出. 解答此题关键在于理解和掌握类的加载过程以及子类继承父类后,重写方法的调用问题: 从程序的执行顺序去解答: 1.编译:当这个类被编译通知后,会在相应的目录下生成两个.class 文件.一个是 Base.class,另外一个就是Base$Sub.class.这个时候类加载器将这两个.class  文件加载到内存 2.Base base= new Sub(): 声明父类变量base对子类的引用,JAVA类加载器将Base,Sub类加载到JVM(Java虚拟

Java虚拟机类加载机制——案例分析

原文出处: 朱小厮 在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬念.建议先看完<Java虚拟机类加载机制>这篇再来看这个,印象会比较深刻,如若不然,也没什么关系~~下面是程序代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package jvm.cla

[转]Java虚拟机类加载机制浅谈

Java语言是一种编译后再经过解释器执行的过程, 解释器主要就是如何处理解释Class文件的二进制字节流.JVM主要包含三大核心部分:运行时数据区,类加载器和执行引擎. 虚拟机将描述类的数据从Class文件加载到内存,并对数据进行校验.准备.解析和初始化,最终就会形成可以被虚拟机使用的Java类型,这就是一个虚拟机的类加载机制.Java中的类是动态加载的,只有在运行期间使用到该类的时候,才会将该类加载到内存中,Java依赖于运行期动态加载和动态链接来实现类的动态使用. 一个类的整个生命周期如下:

tomcat6类加载器与类加载顺序

tomcat6.0.32 com.dyyx.ShareUtils//返回系统当前时间public static String now(); package com.dyyx;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;public class ShareUtils {    private static final String FULL_DATE_FORMAT = "yy