创建类的一个实例时,按照下面步骤进行创建:

1. 给当前类及其父、祖类的所有成员字段分配空间,并给它们赋予默认值

2. 开始执行当前类的构造器

3. 如果当前类有父类,则对父类创建一个实例:从第 2 步开始并把父类当作新的当前类

4. 给当前实例、当前实例的字段进行初始化

5. 执行当前类的构造器的剩余部分代码。

上面的步骤包含一个递归算法。假设类 C 有父类,实例化 C 到第 3 步的时候,需要先创建父类的一个实例,即父类要经历完第 2、3、4、5 步骤之后,才到类 C 继续第 4 步。如果父类也有自己的父类,则父类的父类也要先实例化,才到父类执行第 3 步。依次类推,直到实例化 Object 类,因为 Object 类没有父类。

下面有两个例子进行说明。

1,常规的类实例化

public class Point {
int x, y;
Point(){ x = 1; y = 1; }
}
public class ColoredPoint extends Point {
int color = 0xFF00FF;
}
public class InstanceDemo {
public static void main(){
ColoredPoint cp = new ColoredPoint();
System.out.println(cp.x + " | " + cp.y + " | " + cp.color);
}
}

引起创建类的实例的是代码 new ColoredPoint(),下面是实例创建的步骤:

1. 分配内存给字段 x, y, color, 并给他们赋予默认值

2. ColoredPoint 的构造器被调用

3. ColoredPoint 没有声明构造器,则调用其默认构造器:

  ColoredPoint(){ super(); }

4. 上面的 super() 实际指的是 Point 的无参构造器。Point 的无参构造器最开始部分没有调用其他构造器,则 Java 编辑器提供插入了一个构造器调用,变成:

  Point(){ super(); x = 1; y = 1; }

5. 上面的 super() 实际指的是 Object 的无参构造器。Object 没有父类,不会被插入构造器。Object 的无参构造器没有任何副作用或返回值。被调用的构造器如下

  Object() {  }

6. Point 的字段被初始化。在这里,字段 x, y 无需被初始化。

7. Point 的构造器被继续执行,即对 x , y 分别赋值为 1 。至此,父类 Point 实例化结束

8. ColoredPoint 的字段被初始化。在这里,字段 color 被初始化为 0xFF00FF。

9. ColoredPoint 的构造器被继续执行。在这里,没有其他代码在构造器里面,无需继续执行。至此,ColoredPoint 实例化结束。

2,动态调度在实例化期间的影响

Super,作为父类,在构造器中调用函数 printStatus()。注意,printStatus() 函数被子类重写,所以这里调用的不是 Super 自身的 PrintStatus(),而是其子类的 printStatus().

Sub, 继承于 Super 类,在构造器中调用 printStatus(),然后对变量 age 重写赋值。

InstanceDDDemo, 演示在实例化期间,方法动态调度的影响。

具体代码:

public class Super {

    public Super(){
System.out.println("in Super() ");
printStatus();
} public void printStatus(){
System.out.println("Super.printStatus - ");
}
}
public class Sub extends Super{
private int age = 10; public Sub(){
System.out.println("in Sub() ");
printStatus();
age = 20;
} public void printStatus(){
System.out.println("Sub.printStatus - " + age);
}
}
public class InstanceDDDemo {
public static void main(){
Sub point = new Sub();
System.out.println(" After instance ");
point.printStatus();
}
}

输出:

in Super()
Sub.printStatus - 0
in Sub()
Sub.printStatus - 10
After instance
Sub.printStatus - 20

从输出可见,在执行 Sub 构造里面的代码之前,Sub.printStatus() 已经被调用过一次。

Java 支持方法的动态调度。动态调度是指在运行时才决定选择哪一个多态实现方法。虽然 Super 有自己的 printStutus() 放方法,但是本例子中,Super 构造函数的调用,是由于它被 Sub 类继承,并且 Sub 类在被实例化,所以,这里最原始的目的是创建 Sub 类实例,而 printStutas() 方法对于 Sub 类来说已经被重写了,故在调用父类 Super 的构造器中仍然调用被重写后的 Sub.printStatus().

参考资料

12.5 Creation of New Class Instance, The Java Language Specification, Java SE 8 Edition

Dynamic dispatch, wikipedia

[Java] 实例创建的步骤的更多相关文章

  1. Java - 35 Java 实例

    Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 Java 实例 – 如何编译一个Java 文件? Java 实 ...

  2. Java-Runoob-高级教程:Java 实例

    ylbtech-Java-Runoob-高级教程:Java 实例 1.返回顶部 1. Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. ...

  3. Java 实例

    Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 Java 实例 – 如何编译一个Java 文件? Java 实 ...

  4. Java 学习(21):Java 实例

    Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 //HelloWorld.java 文件 public cla ...

  5. Thrift入门及Java实例演示<转载备用>

    Thrift入门及Java实例演示 作者: Michael 日期: 年 月 日 •概述 •下载配置 •基本概念 .数据类型 .服务端编码基本步骤 .客户端编码基本步骤 .数据传输协议 •实例演示(ja ...

  6. Java线程创建形式 Thread构造详解 多线程中篇(五)

    Thread作为线程的抽象,Thread的实例用于描述线程,对线程的操纵,就是对Thread实例对象的管理与控制. 创建一个线程这个问题,也就转换为如何构造一个正确的Thread对象. 构造方法列表 ...

  7. Java中创建线程的三种方式以及区别

    在java中如果要创建线程的话,一般有3种方法: 继承Thread类: 实现Runnable接口: 使用Callable和Future创建线程. 1. 继承Thread类 继承Thread类的话,必须 ...

  8. java工作流activiti的步骤

    链接:activiti 表名称的解释 工作流从流程定义到创建一个流程实例完成执行步骤(省略bpmn的画法) 工作流的所有操作都是使用流程引擎来进行操作的,流程引擎只是存储流程的过程,而不存储具体的业务 ...

  9. Java开发工具安装步骤内容如下

    Java开发工具安装步骤内容如下 安装 开发工具 STS 链接下载网址 eclipse 链接下载网址 JDK安装 jdk链接下载地址 Marven环境 marven链接下载地址 Tomcat tomc ...

随机推荐

  1. Java基础知识强化之IO流笔记07:自定义的异常概述和自定义异常实现

    1. 开发的时候往往会出现很多问题(java内部系统框架中没有提供这些异常) 比如说:考试成绩必须在0~100之间. 很明显java没有对应的异常,需要我们自己来做一个异常. (1)继承自Except ...

  2. 使用Javascript限制文本框只允许输入数字

    很多时候需要用到限制文本框的数字输入,试过许多方法,都不太理想,遂决定自己实现一个来玩玩.曾经使用过的方法通过onkeydown事件来控制只允许数字: <input onkeydown=&quo ...

  3. Node.js中url的详解

    var url = require('url');var str = 'http://zhufengnodejs:123@github.com:80/2016jsnode?name=zfpx& ...

  4. 一些css小用法总结(持续更新~)

    1.用:before和:after实现小尖角效果 <div class="div"></div> .div{ background: #fff; borde ...

  5. 关于开发C#中的asp.net中gridview控件的使用

    原文网址:http://blog.sina.com.cn/s/blog_67f1b4b201017663.html 1.GridView无代码分页排序: 效果图: 1.AllowSorting设为Tr ...

  6. 解决MVC Json序列化的循环引用问题/EF Json序列化循引用问题---Newtonsoft.Json

    1..Net开源Json序列化工具Newtonsoft.Json中提供了解决序列化的循环引用问题: 方式1:指定Json序列化配置为 ReferenceLoopHandling.Ignore 方式2: ...

  7. ViewHolder的作用和用法

    一直都看别人用ViewHolder,自己也用过,却不知道它的作用是什么?但知道肯定很有用,而且现在android studio应该有直接生产Viewholder的插件, 不过博主我是个新手,就没尝试去 ...

  8. 【C++学习之路】组合类的构造函数

    1 #include <iostream> using namespace std; class A { public: A(){ cout << "调用A无参&qu ...

  9. qt实现类似QQ伸缩窗口--鼠标事件应用

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://blog.csdn.net/hiwubihe/article/details/38678305,qq:1269122125. 上一章 ...

  10. TCP/IP-入门

    Life is not a rehearsal "人生没有彩排" 参考资料:TCP/IP入门经典 (第五版) TCP/IP详解 卷一:协议 一.什么是TCP/IP TCP/IP是一 ...