这篇文章主要讲解Java在创建对象的时候,初始化的顺序。主要从以下几个例子中讲解:

  • 继承关系中初始化顺序
  • 初始化块与构造器的顺序
  • 已经加载过的类的初始化顺序
  • 加载父类,会不会加载子类
  • 创建子类对象会不会创建父类对象

例子1——继承关系中初始化顺序

先看简单的情况,看下面的例子:

public class Father {

    public String fatherVar = "父类构造块初始化";
public static int fatherStaticVar;
public int i;
static {
int i = 100;
System.out.println("父类静态块初始化,i的值为" + i);
System.out.println("父类静态变量初始化,fatherStaticVar的值为" + fatherStaticVar);
} {
System.out.println(fatherVar);
} public Father(){
System.out.println("父类构造函数的初始化,i的值" + i);
}
} public class Son extends Father { public String sonVar = "子类构造块初始化";
public static int sonStaticVar;
public int i;
static {
int i = 101;
System.out.println("子类静态块初始化,i的值为" + i);
System.out.println("子类静态变量初始化,sonStaticVar的值为" + sonStaticVar);
} {
System.out.println(sonVar);
} public Son(){
super();
System.out.println("子类构造函数的初始化,i的值" + i);
} public static void main(String[] args) {
new Son();
}
}

其执行的结果如下:

父类静态块初始化,i的值为100
父类静态变量初始化,fatherStaticVar的值为0
子类静态块初始化,i的值为101
子类静态变量初始化,sonStaticVar的值为0
父类构造块初始化
父类构造函数的初始化,i的值0
子类构造块初始化
子类构造函数的初始化,i的值0

按照结果,我们可以知道在有继承的时候,虽然是创建一个Son对象,但是JVM发现Son对象的类还没有装载,而Son类又继承自Father类,只有加载了Father类,才能加载Son类。于是加载Father类的时候,就会初始化一切静态变量和静态块。所以上文结果中第一行和第二行是父类静态变量和静态块初始化的结果,然后加载完Father类之后,又会加载Son类,同样是初始化Son类的静态块和静态变量,出现上文中第三行和第四行的结果。等这个2个类都加载完了,才开始创建Son对象,因为Son对象,显示调用了Father类的构造器,所以先执行Father类的构造器,出现第五行和第六行的结果,等Father类构造器执行完了,才执行后续Son构造器的内容,所以最后出现了第七行和第八行的结果。

例子2——初始化块与构造器的顺序

在上面的例子中,有2个语句块叫初始化块。在上文的结果中是初始化块的执行是先于构造器的,现在看一下把初始化块的内容放到构造器下面,会是什么的结果

public class InitBlock {

    public InitBlock(){
System.out.println("构造器在执行......");
} {
System.out.println("初始化块1在执行......");
} {
System.out.println("初始化块2在执行......");
} public static void main(String[] args) {
new InitBlock();
}
}

结果如下:

初始化块1在执行......
初始化块2在执行......
构造器在执行......

很显然,无论初始化块写在哪个地方,都是先于构造器执行的,但是初始化块之间的顺序是前面的先初始化,后面在初始化。

例子3——已经加载过的类的初始化顺序

更改一下例子1中的main方法,改成如下:

public static void main(String[] args) {
new Father();
System.out.println("=============");
new Son();
}

结果如下:

父类静态块初始化,i的值为100
父类静态变量初始化,fatherStaticVar的值为0
子类静态块初始化,i的值为101
子类静态变量初始化,sonStaticVar的值为0
父类构造块初始化
父类构造函数的初始化,i的值0
=============
父类构造块初始化
父类构造函数的初始化,i的值0
子类构造块初始化
子类构造函数的初始化,i的值0

结果很有意思,创建父类对象的时候,加载Father类,出现第一行和第二行的结果,但是这个竟然会还把子类的静态变量和静态块初始化?这个原因,例子4在说。 最后执行父类的构造器创建父类对象。当再创建子类的时候,发现父类和子类已经加载过了,所以不会再加载Father和Son类,只会调用父类的构造器,再执行后续子类构造器的内容,创建子类。

例子4——加载父类,会不会加载子类

用一个崭新的例子来看看上面,创建父类的时候,为什么会打印出子类静态初始化执行的结果。

public class StaticFather {
static{
System.out.println("父类静态初始化块");
}
} public class StaticSon extends StaticFather{
static {
System.out.println("子类静态初始化块");
}
} public class Test { public static void main(String[] args) {
new StaticFather();
}
}

结果如下:

父类静态初始化块

这次就不会创建父类的时候,加载子类。例子3之所以出现这个原因 是因为main函数在子类中写的,要执行main函数必须要加载子类。只会加载子类之前要先加载父类,因为不加载父类,只加载子类,怎么让子类调用父类的方法和变量。但是加载父类不会加载子类,反正父类也调用不了子类的方法。

例子5——创建子类对象会不会创建父类对象

做个实验,看一下创建子类对象的时候,到底会不会创建一个父类对象,先说结论:不会。从道理上讲,如果创建任何一个对象都要创建出一个他的父类对象的话,那么整个JVM虚拟机都是Object对象。看下面的实验:

public class ObjectFather {

    public void getInfo(){
System.out.println(getClass().toString());
}
} public class ObjectSon extends ObjectFather{ public ObjectSon(){
super();
super.getInfo();
} public static void main(String[] args) {
new ObjectSon();
}
}

结果如下:

class com.byhieg.init.ObjectSon

可以看出来,创建子类对象时那个父类的Class还是子类的,也就是说创建子类对象并没有创建一个父类的对象,只是说调用了父类的构造器,对父类的属性进行初始化,并且给子类提供了一个super指示器去调用父类中那些变量和方法。

更详细的说,new一个对象实际上是通过一个new指令开辟一个空间,来存放对象。在new ObjectSon()的时候,就只有一个new指令,只会开辟一个空间,所谓初始化父类等等,都是在这个空间中有一个特殊的区域来存放这些数据,而super关键字就是提供了访问这个特殊区域的方法,通过super去访问这个特殊区域。

还可以比较super和this的hashcode来判断,结果必然是两者的hashcode是一致的。

总结

至此,Java初始化的讲解到结束了,基本了覆盖了绝大多数情况中的初始化。

Java初始化过程的更多相关文章

  1. 【Java】Java初始化过程总结

    概述 Java字节代码:byte[] Java类在JVM的表现形式:Class类的对象: Java源代码被编译成class字节码 : Java字节代码 --> Class类的对象: 加载:把Ja ...

  2. (原)Java初始化过程

    先看一个demo,然后进行归纳. class X{ static M m=new M(); Y y=new Y(); public X(){ System.out.print("X" ...

  3. java初始化过程中成员变量

    package day01; class Base{ int j; //1.j=0 Base(){ add(1); //2.调用子类add()方法 System.out.println(j); //4 ...

  4. AJPFX总结Java 程序初始化过程

    觉得Core Java在Java 初始化过程的总体顺序没有讲,只是说了构造器时的顺序,作者似乎认为路径很多,列出来比较混乱.我觉得还是要搞清楚它的过程比较好.所以现在结合我的学习经验写出具体过程: 过 ...

  5. Java类变量和成员变量初始化过程

    一.类的初始化 对于类的初始化:类的初始化一般只初始化一次,类的初始化主要是初始化静态成员变量. 类的编译决定了类的初始化过程. 编译器生成的class文件主要对定义在源文件中的类进行了如下的更改: ...

  6. java代码的初始化过程研究

        刚刚在ITeye上看到一篇关于java代码初始化的文章,看到代码我试着推理了下结果,虽然是大学时代学的知识了,没想到还能做对.(看来自己大学时掌握的基础还算不错,(*^__^*) 嘻嘻……)但 ...

  7. java中对象产生初始化过程

    以前面试的时候,很多公司的笔试题中有关new一个对象有关一系列初始化的过程的选择题目.请看下面的题目. class Parent { static { System.out.println(" ...

  8. 解析Java类和对象的初始化过程

    类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来 ...

  9. 【Thinking in Java】类和对象的初始化过程

    在Java中, 当一个类被调用的时候,它的初始化过程是怎么样的呢? 当一个类被实例化的时候,它的初始化过程又是怎样的呢? 为什么static方法不能未经对象就调用非static方法? 下面我们通过例子 ...

随机推荐

  1. NodeJs之Path

    Path模块 NodeJs提供的Path模块,使得我们可以对文件路径进行简单的操作. API var path = require('path'); var path_str = '\\Users\\ ...

  2. [C#] string 与 String,大 S 与小 S 之间没有什么不可言说的秘密

    string 与 String,大 S 与小 S 之间没有什么不可言说的秘密 目录 小写 string 与大写 String 声明与初始化 string string 的不可变性 正则 string ...

  3. PHP代码优化

    1 代码优化 1 尽量静态化 如果一个方法能被静态,那就声明它为静态的,速度可提高1/4,甚至我测试的时候,这个提高了近三倍. 当然了,这个测试方法需要在十万级以上次执行,效果才明显. 其实静态方法和 ...

  4. MVC还是MVVM?或许VMVC更适合WinForm客户端

    最近开始重构一个稍嫌古老的C/S项目,原先采用的技术栈是『WinForm』+『WCF』+『EF』.相对于现在铺天盖地的B/S架构来说,看上去似乎和Win95一样古老,很多新入行的,可能就没有见过经典的 ...

  5. JQuery阻止事件冒泡

    冒泡事件就是点击子节点,会向上触发父节点,祖先节点的点击事件. 我们在平时的开发过程中,肯定会遇到在一个div(这个div可以是元素)包裹一个div的情况,但是呢,在这两个div上都添加了事件,如果点 ...

  6. SqlServer之数据库三大范式

    分析: 数据库设计应遵循三大范式分别为: 第一范式:确保表中每列的原子性(不可拆分): 第二范式:确保表中每列与主键相关,而不能只与主键的某部分相关(主要针对联合主键),主键列与非主键列遵循完全函数依 ...

  7. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  8. mono for android 用ISharedPreferences 进行状态保持 会话保持 应用程序首选项保存

    由于项目需要 要保持用户登录状态 要进行状态保持 用途就好像asp.net的session一样 登录的时候进行保存 ISharedPreferences shared = GetSharedPrefe ...

  9. 全面解析ASP.NET MVC模块化架构方案

    什么叫架构?揭开架构神秘的面纱,无非就是:分层+模块化.任意复杂的架构,你也会发现架构师也就做了这两件事. 本文将会全面的介绍我们团队在模块化设计方面取得的经验.之所以加了“全面”二字,是因为本文的内 ...

  10. 微信硬件H5面板开发(一) ---- 调用openApi

    微信硬件平台是微信推出连接物与人,物与物的IOT解决方案.也就是说可以通过微信控制各种智能设备.比如一些蓝牙设备.空调.电视等等. 我本身不懂硬件(虽然是电子信息专业),硬件是北航的两个研究生在弄,小 ...