这篇文章主要讲解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. js学习笔记:操作iframe

    iframe可以说是比较老得话题了,而且网上也基本上在说少用iframe,其原因大致为:堵塞页面加载.安全问题.兼容性问题.搜索引擎抓取不到等等,不过相对于这些缺点,iframe的优点更牛,跨域请求. ...

  2. Oracle 的基本操作符

    != 不等于 select empno,ename,job from scott.emp where job!='manager' ^= 不等于 select empno,ename,job from ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(71)-微信公众平台开发-公众号管理

    系列目录 思维导图 下面我们来看一个思维导图,这样就可以更快了解所需要的功能: 上一节我们利用了一个简单的代码例子,完成了与微信公众号的对话(给公众号发一条信息,并得到回复) 这一节将讲解公众号如何设 ...

  4. 博客使用BOS上传图片

    1.博客平台的选定 从大学开始做个人主页算起,最开始是使用html,CSSS写简单的页面,后面大学毕业之后接触到了WordPress,就开始用WordPress搭建网站.现在还维护着一个农村网站.ht ...

  5. 来吧,HTML5之基础标签(下)

    <dialog> 标签 定义对话框或窗口. <dialog> 标签是 HTML 5 的新标签.目前只有 Chrome 和 Safari 6 支持 <dialog>  ...

  6. bash字符串操作

    参考 http://www.cnblogs.com/chengmo/archive/2010/10/02/1841355.html 问题:bash怎么提取字符串的最后一位?例如python中strin ...

  7. 【开发软件】 在Mac下配置php开发环境:Apache+php+MySql

    本文地址 原文地址   本文提纲: 1. 启动Apache 2. 运行PHP 3. 配置Mysql 4. 使用PHPMyAdmin 5. 附录   有问题请先 看最后的附录   摘要: 系统OS X ...

  8. java中if和switch哪个效率快

    首先要看一个问题,if 语句适用范围比较广,只要是 boolean 表达式都可以用 if 判断:而 switch 只能对基本类型进行数值比较.两者的可比性就仅限在两个基本类型比较的范围内.说到基本类型 ...

  9. 修改MySQL默认字符集编码

    好记心不如烂笔头,很多东西当时没记下来,过了就忘了,下次用到时又得浪费好多时间才能解决.今天又遇到修改MySQL默认字符集编码的问题,折腾了半天解决了,赶快记录下来,以后就不用每次折腾了. 查看MyS ...

  10. TypeScript

    TypeScript: Angular 2 的秘密武器(译)   本文整理自Dan Wahlin在ng-conf上的talk.原视频地址: https://www.youtube.com/watch? ...