很有意思的一篇文章

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方法的指令相同。
在虚拟机中存在三种方法的调用指令,这三种调用指令在效率上不同。
接口方法的指令调用,这种调用速度最慢。
普通类方法的调用指令,这种调用速度中等。
构造方法与私有方法调用指令,这种调用速度最快。

转载于:https://www.cnblogs.com/luckygxf/p/4796955.html

Java类的初始化顺序 (静态变量、静态初始化块、变量、初始...相关推荐

  1. Java深度历险(二)——Java类的加载、链接和初始化

    在上一篇文章中介绍了Java字节代码的操纵,其中提到了利用Java类加载器来加载修改过后的字节代码并在JVM上执行.本文接着上一篇的话题,讨论Java类的加载.链接和初始化.Java字节代码的表现形式 ...

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

    Java字节代码的表现形式是字节数组(byte[]),而Java类在JVM中的表现形式是java.lang.Class类的对象.一个Java类从字节代码到能够在JVM中被使用,需要经过加载.链接和初始 ...

  3. java类的运行顺序_Java语言类的基本运行顺序

    本文主要向大家介绍了Java语言类的基本运行顺序,通过具体的代码向大家展示,希望对大家学习Java语言有所帮助.我们以下面的类来说明一个基本的 Java 类的运行顺序:1. public class  ...

  4. 实时错误91,对象变量或with块变量未设置

    问题: 在添加用户信息的过程中,执行到while(mrc.EOF=False)的时候,提示如下错误,对象变量或with块变量未设置 当把光标放到set mrc=executesql(txtsql,ms ...

  5. java类定义的顺序_Java类及对象的初始化顺序

    1.初始化规则: 下面规则优先级从前往后依次降低 0.加载一个类时先初始化基类后初始化扩展类: 1.类的初始化高于对象的初始化: 类的初始化依靠静态代码(被static标识的),静态代码块.静态变量这 ...

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

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

  7. 详解Java类对象执行顺序

    之前了解过static属于类加载顺序优先于对象,成员变量初始化优先于构造方法等等,都是零散的,今天抽出时间系统的总结了一下Java相关加载顺序(大佬请绕开^_^).与君共勉!! 借鉴了@ATJAVA  ...

  8. java中类似实例化顺序_由浅入深详解Java 类的实例化顺序

    文章目录 一.构造方法与代码块的先后顺序 1.1 构造方法 1.2 构造方法与普通代码块 1.3 构造方法与代码块 1.4 总结 二.变量的先后顺序 三.变量.构造方法与代码块 3.1 变量与构造方法 ...

  9. java 类的执行顺序_Java中类的执行顺序

    讲解在代码中: package 类执行顺序; /** * java类执行顺序 * * 1.如果父类有静态成员赋值或者静态初始化块,执行静态成员赋值和静态初始化块 * 2.如果类有静态成员赋值或者静态初 ...

  10. java 初始化顺序_Java中对象初始化顺序的详细介绍

    前言 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.最近我发现了一个有趣的问题,这个问题的答案乍一看下骗过了我的眼睛.看一下这三个类: package com ...

最新文章

  1. 关于java继承中父类方法可见性探讨
  2. SQL Server 数据库表的统计信息的更新
  3. LA3266田忌赛马
  4. android短信安全,[原创]分析了一款android短信木马
  5. 什么是 SAP Spartacus FacadeFactoryService 中的 Resolver
  6. saltstack 基础入门文档
  7. 第三讲 关系映射反演原则
  8. SQL Server 2008 R2——ROW_NUMBER() 去掉不同行中相同列的重复内容
  9. python精确小数点_如何确定小数点是否可以精确地表示为Python float?
  10. 30 分钟带你学透快应用界面开发的最正确姿势
  11. Diablo III 卡Checking for updates的问题解决
  12. 河南分销系统开发|三级分销跟二级分销的区别是什么?
  13. vin码构成以及自动识别的用途。
  14. ubuntu16.04 安装显卡驱动
  15. 2个月,3000节音频,利润30万+这就是赚钱的秘密
  16. 山西大学生计算机设计大赛,2017中国大学生计算机设计大赛山西赛区决赛在中北大学成功举办...
  17. 交游首款游戏曝光 《张狂交游》打破垂头交际
  18. 刚刚!微软又放大招!让草稿几秒钟变App!
  19. (1)ARCH效应、均值方程、GARCH族模型、对波动率建模、预测(包含代码)
  20. python 学习日记 —— dict 字典的用法

热门文章

  1. Postman图片上传用法以及Required request part file is not present的解决方法
  2. js获取前一天/后一天
  3. Linux下安装Apache Maven安装
  4. 我的装机软件清单-备忘
  5. Android开发笔记(九十七)图片的特效处理
  6. mysql的索引和执行计划
  7. Linux下磁盘阵列raid
  8. 【问题】Nginx日志中request_body为空
  9. OC之集合的创建及应用
  10. 安装JDK出现问题 Error opening registry key'software\Javasoft\Java Runtime Environment'