很有意思的一篇文章

1.没有继承

静态变量->静态初始化块->变量->变量初始化块->构造方法

2.有继承的情况

父类静态变量->父类静态初始化块->子类静态变量->子类静态变量初始化块->父类变量初始化->父类变量初始化块->父类构造方法->子类变量初始化->子类变量初始化块->子类构造方法

--------------------------------------------------我是copy分割线---------------------------------------------------------

大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果。这实际上是在考查我们对于继承情况下类的初始化顺序的了解。

我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序以此是(静态变量、静态初始化块)>(变量、初始化块)>构造器。我们也可以通过下面的测试代码来验证这一点: 
Java代码 
public class InitialOrderTest {

// 静态变量 
public static String staticField = "静态变量"; 
// 变量 
public String field = "变量";

// 静态初始化块 
static { 
System.out.println(staticField); 
System.out.println("静态初始化块"); 
}

// 初始化块 

System.out.println(field); 
System.out.println("初始化块"); 
}

// 构造器 
public InitialOrderTest() { 
System.out.println("构造器"); 
}

public static void main(String[] args) { 
new InitialOrderTest(); 

}

运行以上代码,我们会得到如下的输出结果:

静态变量 
静态初始化块 
变量 
初始化块 
构造器

这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果: 
Java代码 
class Parent { 
// 静态变量 
public static String p_StaticField = "父类--静态变量"; 
// 变量 
public String p_Field = "父类--变量";

// 静态初始化块 
static { 
System.out.println(p_StaticField); 
System.out.println("父类--静态初始化块"); 
}

// 初始化块 

System.out.println(p_Field); 
System.out.println("父类--初始化块"); 
}

// 构造器 
public Parent() { 
System.out.println("父类--构造器"); 

}

public class SubClass extends Parent { 
// 静态变量 
public static String s_StaticField = "子类--静态变量"; 
// 变量 
public String s_Field = "子类--变量"; 
// 静态初始化块 
static { 
System.out.println(s_StaticField); 
System.out.println("子类--静态初始化块"); 

// 初始化块 

System.out.println(s_Field); 
System.out.println("子类--初始化块"); 
}

// 构造器 
public SubClass() { 
System.out.println("子类--构造器"); 
}

// 程序入口 
public static void main(String[] args) { 
new SubClass(); 

}

运行一下上面的代码,结果马上呈现在我们的眼前:

父类--静态变量 
父类--静态初始化块 
子类--静态变量 
子类--静态初始化块 
父类--变量 
父类--初始化块 
父类--构造器 
子类--变量 
子类--初始化块 
子类--构造器

现在,结果已经不言自明了。大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。

那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?实际上这取决于它们在类中出现的先后顺序。我们以静态变量和静态初始化块为例来进行说明。

同样,我们还是写一个类来进行测试: 
Java代码 
public class TestOrder { 
// 静态变量 
public static TestA a = new TestA();

// 静态初始化块 
static { 
System.out.println("静态初始化块"); 
}

// 静态变量 
public static TestB b = new TestB();

public static void main(String[] args) { 
new TestOrder(); 

}

class TestA { 
public TestA() { 
System.out.println("Test--A"); 

}

class TestB { 
public TestB() { 
System.out.println("Test--B"); 

}

运行上面的代码,会得到如下的结果:

Test--A 
静态初始化块 
Test--B

大家可以随意改变变量a、变量b以及静态初始化块的前后位置,就会发现输出结果随着它们在类中出现的前后顺序而改变,这就说明静态变量和静态初始化块是依照他们在类中的定义顺序进行初始化的。同样,变量和初始化块也遵循这个规律。

了解了继承情况下类的初始化顺序之后,如何判断最终输出结果就迎刃而解了。

静态块与静态成员的初始化工作与实例化过程无关,实例化必须先执行静态块和静态成员,但并不代表实例化一定会执行静态块和静态成员。只有当实例化的对应的类为加载入虚拟机的时候,才会进行这种操作。有些时候执行静态块或者初始化静态成员不一定就是实例化该类对象才会进行的,例如调研该类的某静态成员或者静态方法,又例如该类的子类被实例化或者调用了静态成员或静态方法等。

还有实例化的实际顺序其实是(省略类初始化过程)
1、进入当前类构造方法。
2、进入父类构造方法递归直到java.lang.Object类构造方法。
3、执行java.lang.Object类构造方法,顺序依次为成员变量初始与初始化块(安装上下文顺序),对应调用的构造方法体。
4、执行java.lang.Object类的直接子类的构造函数,这个过程递归到当前类。
5、当前类执行顺序与前面java.lang.Object类相同。

构造方法的本质其实就是一个普通的无返回参数的名字叫做<init>的方法,不过虚拟机调用这个方法的指令与其它方法不同而已,它的调用指令与调用private方法的指令相同。
在虚拟机中存在三种方法的调用指令,这三种调用指令在效率上不同。
接口方法的指令调用,这种调用速度最慢。
普通类方法的调用指令,这种调用速度中等。
构造方法与私有方法调用指令,这种调用速度最快。

Java类的初始化顺序 (静态变量、静态初始化块、变量、初始...的更多相关文章

  1. java 类的加载,链接,初始化

    本篇的话题,讨论Java类的加载.链接和初始化.Java字节代码的表现形式是字节数组(byte[]),而Java类在JVM中的表现形式是java.lang.Class类的对象.一个Java类从字节代码 ...

  2. java类到底是如何加载并初始化的?

    Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...

  3. JAVA类的加载、连接与初始化

    JAVA类的加载.连接与初始化 类的声明周期总共分为5个步骤1.加载2.连接3.初始化4.使用5.卸载 当java程序需要某个类的时候,java虚拟机会确保这个类已经被加载.连接和初始化,而连接这个类 ...

  4. (转)java类到底是如何加载并初始化的?

    Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...

  5. 实时错误 '91' :对象变量或with块变量未设置

    大家这几天在做学生信息管理系统的时候,出现最多的应该就是这个问题了,“实时错误‘91’:对象变量或with块变量未设置”.如右图: 遇到这个问题,我们首先应该去参考MSDN,不过这时候MSDN似乎没有 ...

  6. sql server常有的问题-实时错误'91' 对象变量或with块变量未设置

    这样的问题,对于我们这样的初学者来说,无疑是一个接触sql server后第一个艰难的问题,“实时错误'91' 对象变量或with块变量未设置”这句话到底透露出什么信息?直至写此博文,我依然看不出什么 ...

  7. VB 对象变量或with块变量未设置

    先看错误代码,以下代码提示 对象变量或with块变量未设置: Dim obj As Object obj = WebBrowser1.Document.getElementById("swi ...

  8. Java类加载信息的顺序:包括静态代码快、静态类变量、非静态代码快、构造方法、普通方法

    JVM运行之前会执行一个叫做类加载器的子系统,叫做ClassLoader,那么类里面那么多“元素”,究竟是个什么顺序呢,写几行代码测试一下,通过给每个方法和代码快和静态变量打上断点来测试: class ...

  9. Java类的加载、链接和初始化

    一.Java的类加载机制回顾与总结: 我们知道一个Java类要想运行,必须由jvm将其装载到内存中才能运行,装载的目的就是把Java字节代码转换成JVM中的java.lang.Class类的对象.这样 ...

  10. java 类的加载、连接和初始化

    JVM和类 调用Java命令运行Java程序时,该命令将会启动一条Java虚拟机进程,不管该Java程序启动了多少条线程,创建了多少个变量,它们都处于该Java虚拟机进程里,共享该JVM进程的内存区. ...

随机推荐

  1. Vue2.0学习--Vue数据通信详解

    一.前言 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.组件间如何传递数据就显得至关重要.本文尽可能罗列出一些常见的数据传递方式,如p ...

  2. Javascript之入门篇(一)

    上一篇学习了什么是JavaScript语言及其作用和特有的特点等,本篇将详细介绍JavaScript一些入门使用方式. 对于初学者来讲,由于JavaScript是嵌入到HTML页面里面的,首先创建一张 ...

  3. [A/C 2007] 数据备份(网络流,堆)

    [A/C 2007] 数据备份(网络流,堆) 给你N各点的位置和K条链,需要用这些链把2K个点连起来,使得链的总长最短.可以随意选择要链的点.n=100000. 这道题居然可以用堆-- 首先,不能把区 ...

  4. django 学习之DRF (二)

    Django学习之DRF02 Serializer序列化器之反序列化操作    1.调⽤序列化器进⾏验证        0.准备序列化器 class BookInfoSerializer(serial ...

  5. linux线程切换问题

    处理器总处于以下状态中的一种: 1.内核态,运行于进程上下文,内核代表进程运行于内核空间: 2.内核态,运行于中断上下文,内核代表硬件运行于内核空间: 3.用户态,运行于用户空间:   一个进程的上下 ...

  6. 牛客国庆集训day5 B 电音之王 (大数乘模)

    链接:https://www.nowcoder.com/acm/contest/205/B来源:牛客网 题目描述 终于活成了自己讨厌的样子. 听说多听电音能加快程序运行的速度. 定义一个数列,告诉你a ...

  7. STP-6-快速生成树协议-新端口角色,状态和类型以及新链路类型

      IEEE 802.1w快速生成树协议(RSTP)增强了802.1D标准,在设计合理的网络中收敛时间远少于1秒.   端口状态从5个减少到3个 丢弃状态是在端口刚启用时的默认状态,边界端口除外,它的 ...

  8. complex 类

    //定义一个复数类Complex,使得下面的代码能够工作. //Complex c1(3,5)//用复数3+5i初始化c1 //complex c2=4.5//用实数4.5初始化c1 //comple ...

  9. java修饰符的一些知识点

    1.java默认的修饰符是不加任何标志,默认为包修饰符,在同一个包下的类都可以对其进行调用.若需要进行跨包调用,往往需要加上修饰符public2.public修饰符对需要调用其的消费者都是可见的,一个 ...

  10. Codeforces Round #529 (Div. 3) C. Powers Of Two

    http://codeforces.com/contest/1095/problem/C 题意:给n找出k个2的幂,加起来正好等于n.例如 9,4:9 = 1 + 2 + 2 + 4 思路:首先任何数 ...