我们参考下面这个例子:

读者可以提前考虑一下,这段程序的输出会是什么。

public class Polymorphism {

    /**
* 创建一个类A
* 该类中有一个方法draw,以及一个构造方法A
*/
static class A{
void draw(){
System.out.println("A.draw()");
}
A(){
System.out.println("A() before draw()");
draw();
System.out.println("A() after draw()");
}
} /**
* 创建一个类B,继承A
* 该类中同样有一个方法draw,以及一个构造方法B
*/
static class B extends A {
private int value=1;
void draw(){
System.out.println("B.draw(),value="+value);
}
B(int v){
value=v;
System.out.println("B.B(),value="+value);
}
} /*现在我们调用B的构造函数,构造一个B*/
public static void main(String[] args) {
new B(5);
}
}

最后的输出结果为

A() before draw()
B.draw(),value=0
A() after draw()
B.B(),value=5

初次分析

可见,当我们试图构造一个B时,应该会优先构造B的父类A,所以会调用父类A的构造函数A(),所以会输出

A() before draw()

这时A调用了draw()方法,因为是构造B类,而B类覆盖重写A类的draw()方法,所以这里应该调用的是B类重写过后的draw()方法,而B类的value默认值为1,所以会输出

B.draw(),value=1
A() after draw()

此刻父类A已经完成构造,所以接着才会构造B,调用B的构造函数B(),且传入的值为5,所以会输出

B.B(),value=5

而实际上,最后输出的并不是

B.draw(),value=1

而是

B.draw(),value=0

最后在《Thinking in Java》一书中找到了类似的例子,其中给出了一套正确的初始化顺序

(1)在其他任何事物之前,将分配给对象的存储空间初始化为二进制的零

(2)如前所述那样调用基类构造器。此时,调用被覆盖后的draw()方法  (要在调用B构造器之前调用),由于步骤1的缘故,我们此时会发现value的值为0。

(3)按照声明的顺序调用成员的初始化方法。

(4)调用导出类的构造器主体。

Java 多态方法构造器执行方法的更多相关文章

  1. Java 多态 父类和子类方法的访问控制权限

    Java 多态 父类和子类方法的访问控制权限 @author ixenos 父类和子类方法的访问控制权限 继承是为了扩展类的功能,而这种扩展显然就是对一个原始类的扩展,目的还是向上转型来调用,所以这就 ...

  2. 要想学好Java编程,构造器、方法重载、this关键字、垃圾回收机制,这4关一定要过!

    有人说,你应该关注时事.财经,甚至流行的电影.电视剧,才有可能趁着热点写出爆文:有人说,你别再写“无聊”的技术文了,因为程序员的圈子真的很小,即便是像鸿洋那样的招牌大牛,文章是那么的干货,浏览量有多少 ...

  3. Java基础03 构造器与方法重载

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在方法与数据成员中,我们提到,Java中的对象在创建的时候会初始化(initial ...

  4. Java基础03 构造器与方法重载(转载)

    显式初始化要求我们在写程序时就确定初始值,这有时很不方便.我们可以使用构造器(constructor)来初始化对象.构造器可以初始化数据成员,还可以规定特定的操作.这些操作会在创建对象时自动执行. 定 ...

  5. java 多态 ---父类调用子类方法

    package test1;//多态的体现import javax.print.attribute.standard.RequestingUserName;import java.util.Scann ...

  6. JAVA多线程间隔时间段执行方法

    import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class ManyProject ...

  7. java反射获取类的类名、属性名、属性类型、方法、执行方法、构造函数

    public class Demo02 { @SuppressWarnings("all") public static void main(String[] args) thro ...

  8. 用arthas的watch方法观察执行方法的输入输出

    watch 的参数比较多,主要是因为它能在 4 个不同的场景观察对象 参数名称 参数说明 class-pattern 类名表达式匹配 method-pattern 方法名表达式匹配 express 观 ...

  9. Java反射、动态加载(将java类名、方法、方法参数当做参数传递,执行方法)

    需求:将java类名.方法.方法参数当做参数传递,执行方法.可以用java的动态加载实现   反射的过程如下:     第一步:通过反射找到类并创建实例(classname为要实例化的类名,由pack ...

随机推荐

  1. 18年selenium3+python3+unittest自动化测试教程(上)

    第一章 自动化测试课程介绍和课程大纲 1.自动化测试课程介绍 简介:讲解什么是自动化测试和课程大纲讲解,课程需要的基础和学后的水平 python3.7+selenium3 pycharm 第二章自动化 ...

  2. TCP套接字

    端口的概念 每个电脑一根网线,但是你挂着QQ的同时还可以浏览网页.两个不同应用的数据在同一根网线里是如何传输的呢?根据七层互联网模型,这个功能由运输层(TCP是运输层主要协议)实现.怎么实现呢,在网络 ...

  3. Vue--- VueX组件间通信链接(共有方法放入了扩展目录store里面) 1.2

    Vuex结构图再仔细看 Vuex原理: 就是  把共有属性放入到一个公共的地方,进行使用 多组件共享状态, 之前操作方式,由父组件传递到各个子组件. 当路由等加入后,会变得复杂. 引入viewx 解决 ...

  4. mysqldump备份与基于bin-log实现完全恢复

    MySQL数据库备份是一项非常重要的工作,mysql的备份主要分为逻辑备份和物理备份,同时,不同的生产环境要备份的策略也不会不同.下面先说一说备份时要考虑到的一些因素,然后再实际操作进行不同方式的数据 ...

  5. Struts2的动态方法,及result跳转方式,全局结果以及默认的action的配置

    Action动态方法的调用 首先我们需要在struts.xml中去配置一个常量值如下 那么去哪找呢?找到Struts-core.jar并打开 method属性 <action name=&quo ...

  6. MySql外键建立在哪里(更新)

    一对一的时候:分为主表和附表  外键建立在附件上  附表的外键关联到主表的主键上,Example:学生表和学生信息表,在学生信息表上建立外键 一对多的时候:分为一和多  外键建立在多上  Exampl ...

  7. XML文档处理

    1)CDATA部分用<![CDATA[和]]>来限定其界限,它们是字符数据的一种特殊形式,可用使用它们来囊括那些含有<.>,&之类字符的字符串,而不必将它们解释为标记例 ...

  8. Delphi初始化与结束化

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  9. django开发傻瓜教程-3-celery异步处理

    Ref: https://www.jianshu.com/p/6f8576a37a3e https://blog.csdn.net/Demo_3/article/details/78119951 ht ...

  10. js bom和dom

    一, 前言 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的一些交互,我们需要继续学习BOM ...