图文详解Java中class的初始化顺序

class的装载

在讲class的初始化之前,我们来讲解下class的装载顺序。

以下摘自《Thinking in Java 4》

由于Java 中的一切东西都是对象,所以许多活动

变得更加简单,这个问题便是其中的一例。正如下一章会讲到的那样,每个对象的代码都存在于独立的文件中。除非真的需要代码,否则那个文件是不会载入的。通常,我们可认为除非那个类的一个对象构造完毕,否则代码不会真的载入。由于static 方法存在一些细微的歧义,所以也能认为“类代码在首次使用的时候载入”。

首次使用的地方也是static 初始化发生的地方。装载的时候,所有static 对象和static 代码块都会按照本来的顺序初始化(亦即它们在类定义代码里写入的顺序)。当然,static 数据只会初始化一次。

简要的说就是,在类有继承关系时,类加载器上溯造型,进行相关类的加载工作。

比如:

Class B extends Class A
当我们new B()时,类加载器自动加载A的代码

class的初始化顺序

通常是以下这样的初始化顺序:

(static对象和static代码块,依据他们的顺序进行初始化)>成员变量>构造函数

测试代码

public class ClassInit {

  /**
   * @Title:       main
   * @Description:   类初始化顺序测试
   * @param:       @param args
   * @return:     void
   * @throws
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    new B();
  }

}

class A {
  static{
    System.out.println("A的static代码块...");
  }
  public String s1 = prtString("A的成员变量...");
  public static String s2 = prtString("A的static变量...");
  public A(){
    System.out.println("A的构造函数...");
  }

  public static String prtString(String str) {
    System.out.println(str);
    return null;
  }
}

class B extends A{
  public String ss1 = prtString("B的成员变量...");
  public static String ss2 = prtString("B的static变量...");
  public B(){
    System.out.println("B的构造函数...");
  }
  private static A a = new A();
  static{
    System.out.println("B的static代码块...");
  }
  {
    System.out.println("代码块...");
  }
}

测试结果

A的static代码块...
A的static变量...
B的static变量...
A的成员变量...
A的构造函数...
B的static代码块...
A的成员变量...
A的构造函数...
B的成员变量...
代码块...
B的构造函数...

总结

以上就是Java中class的初始化顺序的全部内容,希望对大家使用Java能有所帮助。

(0)

相关推荐

  • java父类和子类初始化顺序的深入理解

    继承类的构建过程是向外扩散的,子类初始化了,父类一定也初始化了 复制代码 代码如下: class Art{ Art(){  System.out.println("Art"); }}class Drawing extends Art{ Drawing(){  System.out.println("Drawing"); }}public class Cartoon extends Drawing { Cartoon(){  System.out.println(&q

  • Java类初始化和实例化中的2个“雷区”

    在考虑类初始化时,我们都知道进行子类初始化时,如果父类没有初始化要先初始化子类.然而事情并没有一句话这么简单. 首先看看Java中初始化触发的条件: (1)在使用new实例化对象,访问静态数据和方法时,也就是遇到指令:new,getstatic/putstatic和invokestatic时: (2)使用反射对类进行调用时: (3)当初始化一个类时,父类如果没有进行初始化,先触发父类的初始化: (4)执行入口main方法所在的类: (5)JDK1.7动态语言支持中方法句柄所在的类,如果没有初始化

  • java类中元素初始化顺序详解

    复制代码 代码如下: public class Test4 {    @Test    public void test(){        child child = new child();    }} class parent{    public static String parentStaticField = "父类静态变量";    public String parentNormalField ="父类普通变量";    static {      

  • Java中static静态变量的初始化完全解析

    静态变量初始化顺序 1.简单规则 首先先看一段最普遍的JAVA代码: public class Test { public static Test1 t = new Test1(); public static int a = 0; public static int b; public static void main(String[] arg) { System.out.println(Test.a); System.out.println(Test.b); } } class Test1

  • 浅谈Java变量的初始化顺序详解

    规则1(无继承情况下):对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器证明代码: 复制代码 代码如下: public class InitialOrderTest {    // 静态变量    public static String staticField = "静态变量";    // 变量    public String field = "变量";    // 静

  • Java数组声明、创建、初始化基础

    一维数组的声明方式: type var[]; 或type[] var; 声明数组时不能指定其长度(数组中元素的个数), Java中使用关键字new创建数组对象,格式为: 数组名 = new 数组元素的类型 [数组元素的个数] 实例: TestNew.java: 程序代码: public class TestNew { public static void main(String args[]) { int[] s ; int i ; s = new int[5] ; for(i = 0 ; i

  • java对象初始化顺序验证示例

    复制代码 代码如下: public class Derive extends Base {    private Member m1 = new Member("Member 1");    {        System.out.println("Initial Block()");    } public Derive() {        System.out.println("Derive()");    } private Member

  • 通过java字节码分析学习对象初始化顺序

    复制代码 代码如下: mockery.checking(new Expectations() { {               one(new Object()).toString();               will(returnValue(""));           }       }); 下面写一个写一个简单的类演示这个例子 复制代码 代码如下: public class Test { int i = 1;    {        int j = 1;       

  • Java对象初始化顺序的使用

    单一类:(静态成员变量&静态初始化块)<(成员变量&初始化块)<构造函数 复制代码 代码如下: public class 对象初始化顺序 {    public static void main(String[] args){        Person p = new Person();    }}class Person{    public static String staticfield ="静态成员变量";    public String fi

  • 图文详解Java中class的初始化顺序

    class的装载 在讲class的初始化之前,我们来讲解下class的装载顺序. 以下摘自<Thinking in Java 4> 由于Java 中的一切东西都是对象,所以许多活动 变得更加简单,这个问题便是其中的一例.正如下一章会讲到的那样,每个对象的代码都存在于独立的文件中.除非真的需要代码,否则那个文件是不会载入的.通常,我们可认为除非那个类的一个对象构造完毕,否则代码不会真的载入.由于static 方法存在一些细微的歧义,所以也能认为"类代码在首次使用的时候载入".

  • 图文详解Java中的序列化机制

    目录 概述 对象序列化和反序列化机制 修改默认的序列化机制 使用transient关键字 自定义readObject.writeObject方法 实现Externalizable接口 serialVersionUID的作用 使用序列化clone 概述 java中的序列化可能大家像我一样都停留在实现Serializable接口上,对于它里面的一些核心机制没有深入了解过.直到最近在项目中踩了一个坑,就是序列化对象添加一个字段以后,使用方系统报了反序列化失败,原因是我们双方的序列化对象没有加上seri

  • 详解java中继承关系类加载顺序问题

    详解java中继承关系类加载顺序问题 实例代码: /** * Created by fei on 2017/5/31. */ public class SonClass extends ParentClass{ public SonClass(){ System.out.println("SonClass's constructor"); } { System.out.println("SonClass's block");} static { System.out

  • 详解Java中的实例初始化块(IIB)

    在 Java 语言中的类初始化块 文章中我们简单的介绍了下 Java 中的实例初始化块 ( IIB ).不过我觉得介绍的有点简单了,于是,再写一篇文章详细介绍下吧. Java 语言中,存在三种操作:方法 .构造函数 和 初始化块. 其中初始化块又分为 实例初始化块 ( IIB ) 和 静态初始化块.本章节,我们主要介绍实例初始化块. 实例初始化块 用于初始化实例变量. 实例初始化块 会在初始化类的一个实例时执行,而且在构造函数之前就执行.并且每次创建类的对象时它们都会执行. 实例化块的语法 实例

  • 图文详解Java中的字节输入与输出流

    目录 字节输入流 字节输入流结构图 FileInputStream类 构造方法: 常用读取方法: 字节输出流 字节输出流结构图: FileOutputStream类 构造方法: 常用写入方法: 总结 字节输入流 java.io.InputStream抽象类是所有字节输入流的超类,将数据从文件中读取出来. 字节输入流结构图 在Java中针对文件的读写操作有一些流,其中介绍最常见的字节输入流. FileInputStream类 FileInputStream流被称为字节输入流,对文件以字节的形式读取

  • 图文详解Java的反射机制

    目录 1.什么是反射 2.Hello,java反射 3.java程序运行的三个阶段 4.反射相关类 5.反射的优化 6.Class类分析 7.获取Class对象的六种方式 8.类加载机制 动态加载和静态加载 类加载流程概述 加载阶段 连接阶段 初始化 9.通过反射获取类的结构信息 1.什么是反射 反射就是Reflection,Java的反射是指程序在运行期可以拿到一个对象的所有信息. 加载类后,在堆中就产生了一个class类型的对象,这个对象包含了类的完整结构的信息,通过这个对象得到类的结构.这

  • 详解JAVA中implement和extends的区别

    详解JAVA中implement和extends的区别 extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,Java中不支持多重继承,但是可以用接口来实现,这样就要用到implements,继承只能继承一个类,但implements可以实现多个接口,用逗号分开就行了比如class A extends B implements C,D,E implements是一个类实现一个接口用的关键字,他是用来实现接口中定义的抽象方法. 还有几点需要注意: (1

  • 详解java中的四种代码块

    在java中用{}括起来的称为代码块,代码块可分为以下四种: 一.简介 1.普通代码块: 类中方法的方法体 2.构造代码块: 构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行. 3.静态代码块: 用static{}包裹起来的代码片段,只会执行一次.静态代码块优先于构造块执行. 4.同步代码块: 使用synchronized(){}包裹起来的代码块,在多线程环境下,对共享数据的读写操作是需要互斥进行的,否则会导致数据的不一致性.同步代码块需要写在方法中. 二.静态代码块和构造

  • 详解Java 中的UnitTest 和 PowerMock

    学习一门计算机语言,我觉得除了学习它的语法外,最重要的就是要学习怎么在这个语言环境下进行单元测试,因为单元测试能帮你提早发现错误:同时给你的程序加一道防护网,防止你的修改破坏了原有的功能:单元测试还能指引你写出更好的代码,毕竟不能被测试的代码一定不是好代码:除此之外,它还能增加你的自信,能勇敢的说出「我的程序没有bug」. 每个语言都有其常用的单元测试框架,本文主要介绍在 Java 中,我们如何使用 PowerMock,来解决我们在写单元测试时遇到的问题,从 Mock 这个词可以看出,这类问题主

  • 详解JAVA中接口的定义和接口的实现

    1.接口的定义 使用interface来定义一个接口.接口定义同类的定义类似,也是分为接口的声明和接口体,其中接口体由常量定义和方法定义两部分组成.定义接口的基本格式如下: [修饰符] interface 接口名 [extends 父接口名列表]{ public static final 常量; public abstract 方法; } 修饰符:可选,用于指定接口的访问权限,可选值为public.如果省略则使用默认的访问权限. 接口名:必选参数,用于指定接口的名称,接口名必须是合法的Java标

随机推荐