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

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. 使用jQuery Mobile和Phone Gap开发Android应用程序(转)

    经过了一段时间的学习,初步了解了该如何使用jQuery Mobile和 Phone Gap来开发一个Android应用程序,也想把这些东西介绍给大家. 1. 软件准备 要进行android app的开 ...

  2. discuz! X3 门户文章添加字段

    1. 首先需要去数据表里[llgp_portal_article_title]手动添加需要添加的字段. (注意: 数据表前缀依据自己的设置而定) 2. 修改模版template\default\por ...

  3. codevs 1047 邮票面值设计

    /* 开始没啥好的思路 暴力吧 T的太严重 加了k>n的特判 结果没数据…..然后又暴力生成了几组答案 打表 然而有没有数据 华丽的爆零了 正解 回溯+DP 回溯生成k数组 然后DP找最优解更新 ...

  4. Adobe DreamweaverCS6安装及破解(序列号+破解补丁)

    一:安装 1) Adobe DreamweaverCS6中文版下载地址:Adobe DreamweaverCS6中文版下载 2)Adobe DreamweaverCS6安装及破解说明下载地址:Adob ...

  5. Linux SSH: key, agent, keychain

    以前遇到过一个问题,在用有些 Linux 发行版时,用 ssh-keygen 产生好了密钥对并上传到了目标服务器,但每次登录都要重新输入. 这与 ssh-agent 有关,看如下 man ssh-ag ...

  6. Android Studio中关于Project与Module

    在Android Studio中一个Project和Eclipse中的WorkSpace是相似的,而一个Module与Eclipse中的Project是相似的(大致可以这么的认为) 若在Android ...

  7. Android界面刷新方法

    Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中 ...

  8. 织梦dede自定义内容分页,datalist运用实例

    在/plus文件夹中新建一个ceshi.php文件..<?php require(dirname(__FILE__)."/../include/common.inc.php" ...

  9. Linux和windows下清除svn保存的账号密码信息

    linux是什么用户登录就是什么用户的home下,如root用户就是/root,如果xiangdong就是/home/xiangdong 用Svn时会有一种需求是需要换个帐号测试一下什么的,但往往有缓 ...

  10. centos yum

    1.介绍 yum(全 称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器.基於RPM包管理,能够从指定的服务器 ...