###############################

今天总结一下,new对象的初始化过程。

###############################

首先,当不含static成员时,先看一下案例图:

如图所示,我们先定义相关类,Building,House(继承Building),Villa(继承House),同时,House有成员变量LivingRoom,LivingRoom有成员变量Bed和Desk。

具体代码实现如下:

 //建筑
class Building {
public Building() {
System.out.println("Building");
}
}
//房子
class House extends Building{
public LivingRoom livingRoom = new LivingRoom();//卧室
public House() {
System.out.println("House");
}
}
//别墅
class Villa extends House{
public Villa () {
System.out.println("Villa");
}
}
//卧室
class LivingRoom {
public Bed bedFirst = new Bed();//床
public Desk deskFirst = new Desk();//桌子 public LivingRoom () {
System.out.println("LivingRoom");
}
}
//床
class Bed {
public Bed () {
System.out.println("Bed");
}
}
//桌子
class Desk {
public Desk () {
System.out.println("Desk");
}
}
此时,我们new Villa():
public class InitializeDemo {
@Test
public void testInitialize() {
Villa villa = new Villa();
}
}
执行结果为:
Building
Bed
Desk
LivingRoom
House
Villa

  在此案例中,我们在创建Villa对象时,会先试着创建Villa的父类House的对象,但House也有父类Building,Building还有父类object。因此,实际上,本类会先创建object对象并初始化,在object对象创建并初始化后,会创建building对象,building对象没有成员变量,所以直接执行构造器,打印出building。

  接着,开始创建house对象,house对象有成员变量livingRoom,因此,会先初始化livingRoom,创建livingRoom时,也会先创建livingRoom的父类object对象并初始化没其次再创建livingRoom实例,livingroom同样有两个成员变量bed和desk,因而会按两个成员变量的定义顺序,先后创建bed和desk。初始化成员变量成功后,执行livingroom的构造器,打印livingroom。初始化livingroom成功后,开始执行house的构造器,打印house。

  最后,在house初始化成功后,执行了Villa的构造器,打印出Villa。

  初始化成功。

其次,当有static成员时

 class Family {
Family (Class className) {
System.out.println("创建Family对象");
System.out.println(className.getName());
}
}
class Person {
Person() {
System.out.println("创建Person对象");
}
public static Family family = new Family(Person.class);
static {
System.out.println("执行Person静态代码块");
}
{
System.out.println("执行Person代码块");
}
}
public class Student extends Person {
public Student() {
System.out.println("创建student对象");
}
{
System.out.println("执行Student代码块");
}
static {
System.out.println("执行Student静态代码块");
}
public static Family staticFamily = new Family(Student.class);
@Test
public void test() {
System.out.println("=============");
}
public Family family = new Family(Student.class);
}
执行结果:
创建Family对象
com.tca.thinkInJava.chap7.Person
执行Person静态代码块
执行Student静态代码块
创建Family对象
com.tca.thinkInJava.chap7.Student
执行Person代码块
创建Person对象
执行Student代码块
创建Family对象
com.tca.thinkInJava.chap7.Student
创建student对象

  1.首先在执行@test方法时,必须创建student的实例对象。

  2.要创建student的实例对象,第一步先加载student父类person和student类的字节码,并对相关静态成员变量进行初始化,执行静态代码块。

  3.首先加载父类person字节码,静态成员变量public static family ,family优于静态代码块前声明,所以先对静态成员变量family进行初始化。创建family对象,打印“创建family对象”,“xxxxxx”。

  4.加载完person字节码后,再加载student字节码。静态代码块再静态成员public static family staticfamily之前声明,所以先执行静态代码块,打印“执行student静态代码块”,在进行成员变量初始化,执行“创建family对象”,“xxxxxxxxxx”。

  5.创建student父类person的实例对象,创建实例对象时,先进行非静态成员变量初始化和代码块的执行,在执行构造器方法。所以先打印“执行person代码块”,再打印“创建person对象”。父类对象创建和初始化完毕。

  6.创建子类对象student,先进行非静态成员变量初始化和代码块的执行,在执行构造方法。代码块的声明再非静态成员变量声明之前,所以先执行代码块,打印“执行student代码块”,再对family进行初始化,创建family对象,打印“创建family对象”,“xxxxxxxxxxx”。

  7.执行test测试方法。

总结:

  当不含static成员时,我们new一个对象A时,首先会先创建A类的父类B的实例对象,如果B类仍有C类,会先创建父类C的对象,以此类推,是一个递归创建的过程;当该类的父类对象已经全部创建并初始化时,会对该类进行创建和初始化。但在对该类进行初始化时,会先初始该类对象的成员变量,再执行该类的构造方法。成员变量的初始化和代码块的执行顺序,由它们声明顺序决定的,按顺序依次初始化或执行,但均在构造器方法之前执行。

  当有static成员时,在该类第一次被JVM加载时,静态成员变量只会被初始化一次,静态代码块只会被执行一次。会先加载父类字节码,再加载子类字节码,如果有创建某类的实例对象,也是在该类的父类和该类的字节码加载完成之后,才会实例化该类父类的实例对象和该类的实例对象。静态成员变量的初始化和静态代码块的执行顺序,是由它们的声明顺序决定的,按顺序依次初始化或执行。

new一个对象的初始化过程的更多相关文章

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

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

  2. Java对象相关元素的初始化过程

    1.类的成员变量.构造函数.成员方法的初始化过程 当一个类使用new关键字来创建新的对象的时候,比如Person per = new Person();JVM根据Person()寻找匹配的类,然后找到 ...

  3. java 子类的实例化和代码块初始化过程

    1,子类的实例化 1,子父类中的构造函数的特点. 在子类构造对象时,发现,访问子类构造函数时,父类也运行了. 为什么呢? 原因是:在子类的构造函数中第一行有一个默认的隐式语句. super(); 子类 ...

  4. -1-2 java 面向对象基本概念 封装继承多态 变量 this super static 静态变量 匿名对象 值传递 初始化过程 代码块 final关键字 抽象类 接口 区别 多态 包 访问权限 内部类 匿名内部类 == 与 equal

    java是纯粹的面向对象的语言 也就是万事万物皆是对象 程序是对象的集合,他们通过发送消息来相互通信 每个对象都有自己的由其他的对象所构建的存储,也就是对象可以包含对象 每个对象都有它的类型  也就是 ...

  5. 【软件构造】-<笔记>-浅谈java中类的初始化过程

    编写java程序时,每创建一个新的对象,都会对对象的内容进行初始化. 每一个类的方法中的局部变量都有严格的初始化要求,因此假如写出下面的程序: void f(){ int i; i++; } 编译时就 ...

  6. Spark-源码-TaskScheduler初始化过程, ClientActor向Master发送注册任务信息过程

    Spark版本 1.3 Spark源码 Spark.createTaskScheduler TaskScheduler初始化过程 1.// SparkContext中 /** * Create a t ...

  7. Java 静态static关键字,main函数,对象的初始化过程,对象调用成员,单例模式的设计,静态代码块(6)

    Java 静态static关键字,静态代码块详情参考:static的使用原理讲解http://www.cnblogs.com/itcqx/p/5519464.html main函数: java Mai ...

  8. SpringIOC初始化过程--详解

    SpringIOC初始化过程 相信大家都知道Spring这个东西,我们经常来用他一些特性,比如说他的AOP,IOC,那今天就带大家解析下SpringIOC的加载过程. 我们来看一个例子 Annotat ...

  9. vue 快速入门 系列 —— Vue 实例的初始化过程

    其他章节请看: vue 快速入门 系列 Vue 实例的初始化过程 书接上文,每次调用 new Vue() 都会执行 Vue.prototype._init() 方法.倘若你看过 jQuery 的源码, ...

随机推荐

  1. FormData使用方法详解,以及在IE9环境下,前端的文件上传问题

    FormData的主要用途有两个: 1.将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率. 2.异步上传文件 一.创建formData对象 ...

  2. Linux之自动化部署

    No.1 自动化部署git项目 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 ...

  3. Winform中自定义添加ZedGraph右键实现设置所有Y轴刻度的上下限

    场景 Winforn中实现ZedGraph自定义添加右键菜单项(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...

  4. Scss换肤

    项目中虽然没有一键换肤的要求,但是产品要求后期能换主题.在开发组件中涉及到主题的地方,要提取一些公用的变量,不要直接写死样式值.但是如果只是定义一些变量的话,只是完成控制颜色等值的提取.后期切换的话需 ...

  5. JQuery 获取元素到浏览器可视窗口边缘的距离

    获取元素到浏览器可视窗口边缘的距离 by:授客 QQ:1033553122 1.   测试环境 JQuery-3.2.1.min.js 下载地址: https://gitee.com/ishouke/ ...

  6. 【React Native】在原生和React Native间通信(RN调用原生)

    一.从React Native中调用原生方法(原生模块) 原生模块是JS中也可以使用的Objective-C类.一般来说这样的每一个模块的实例都是在每一次通过JS bridge通信时创建的.他们可以导 ...

  7. 团队项目之Scrum1

    小组:BLACK PANDA 时间:2019.11.16 部分 得分项 分数 完成内容 第 1 篇 Scrum 冲刺博客 各个成员在 Alpha 阶段认领的任务 3 明日各个成员的任务安排 3 用户登 ...

  8. ElasticSearch7 设置外网访问失败

    elasticsearch外网访问9200端口失败,bootstrap checks failed,the default discovery settings are unsuitable for ...

  9. Unity如何更改精灵中心点

      Unity虽然可以改中心点但是仅支持几个特定位置. 如果是一个你是切割的精灵,则可以进入精灵编辑器中调整 打开精灵编辑器后按调整如下图所示的pivot选项,我在这里把精灵调整成了右上. 在精灵编辑 ...

  10. GO语言规范

    1.golang的命名推荐使用驼峰命名法,必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母.数字或下划线. 2.golang中根据首字母的大小写来确定可以访问的权限.无论是方 ...