当前课程知识点:Java程序设计 > 第四章 接口与多态 > 4.5-构造方法与多态性 > 构造方法和多态性
大家好
欢迎回来继续学习
JAVA语言程序设计
在这一节呢
我们来学习构造方法与多态性
构造方法与其他方法是有区别的
构造方法是不具有多态性的特点的
但是我们仍然需要知道
如果我们在构造方法中
要调用了多态的方法会怎么样呢
会发生什么呢
接下来我们有必要来了解一下
当构造子类对象的时候
构造方法的调用顺序是什么
那么首先会调用它超类的构造方法
如果有超类的话
那这个步骤呢
还会不断的去重复
直到最顶上那个超类
也就是所有类的
最上层超类object类
所以最远超类的构造方法
最先被调用
那么上头一级一级超类的构造方法
都被执行完了以后
才会执行当前子类的
构造方法体的其他语句
在这个例题中呢
我们设计了一个点类
一个球类和一个运动的球类
这个运动的球类movingBall
是继承球类ball
好 我们看这个点类
其中有一个toString方法
它是覆盖了从超类继承过来的
也就是object类里面
定义的这个toString方法
然后我们看这个点类呢
它的构造方法
一个是没有参数的
一个是有参数的
那么这个ball球类
它包含一个中心点
这是一个组合了
它其中有一个变量是已经存在的
类的对象
就是对象的引用center
是point类型的
另外呢有基本类型的数据成员
那我们来看这个ball类的构造方法
这个没有参数的构造方法呢
它方法体是空的
没做什么实质性的初始化
另外一个是有参数的构造方法
那么它第一件事儿
就是要构造一个点类的对象
用来作为圆心
然后再给半径来赋值
那么这个ball类
有参数的构造方法呢有两个
一个是有三个参数的构造方法
一个是有四个参数的构造方法
那么这多一个参数多了什么呢
多了对颜色的赋值
那么为了构造方法的算法统一
我们在这个有四个参数的
构造方法里面
直接去调用了它的另一个
具有三个参数的构造方法
而不是把同样的算法重写一遍
当然了同样在这个类中
也是覆盖了这个从超类继承
过来的toString方法
有了自己的实现
再看这个movingBall
它继承了ball
增加了自己的数据成员
写了自己的构造方法
在这个有参数的构造方法中呢
注意它的第一句
就是首先调用它的超类的构造方法
然后才是对其他数据的初始化
同样在这个movingBall类里边
也是覆盖了toString方法
有自己独特的
将对象转换成字符串的
这个具体算法
注意子类是不能够直接存取
父类中声明的私有数据成员的
所以我们注意到
在这个toString方法中
要调用它超类的
就是ball类的toString方法
用super.toString来调用
去输出这个ball里面的
相应的属性值
现在我们来测试一下
在这个测试程序中呢
我们构造一个movingBall对象
那么首先构造的时候
肯定我们看
要调用它的构造方法的时候
构造方法的第一句
就会调用它超类的构造方法
而它超类呢
会调用自己的另一个构造方法
并且首先去调用
它的组件圆心point类的构造方法
那么最后才是执行movingBall的
构造方法体做其他的初始化
那接下来呢
我们输出这个movingBall对象
在这里面呢
就会自动的将这个对象
转换成字符串string
怎么转换呢
就会调用这个toString方法
而toString方法
又会调用它超类的toString方法
调用这个超类的toString方法
那么这个超类的toString方法呢
它其中要输出的圆心信息呢
是点类信息
又要再调用center
这个圆心它的toString方法
就是point类toString方法
所以我们看到得到的输出结果
就是这样的结果
好 现在我们归纳一下
在这个例子中
构造方法的调用顺序
当我们去构造一个
movingBall对象的时候呢
首先会去调用它的超类
ball的构造方法
ball有两个构造方法
其中有四个参数的这个构造方法呢
它又去调用了它自己本类的
具有三个参数的构造方法
然后在这个ball类里面呢
它是内嵌了一个point对象
点对象作为组件的
作为对象成员
所以它又去调用了point的构造方法
好
知道了在有继承关系的时候
子类对象构造的时候
构造方法的调用次序
那么接下来
是时候考虑这个问题了
我们在构造方法中
能不能去调用其他的
动态绑定的这个多态的方法呢
因为在调用构造方法的时候
是一个对象还没有完成
它的构造的时候
这个时候它的一些属性
还没有初始化好
对象还没有完全的构造好
如果在这个时候
去调用多态的方法
实际上是会有一些隐患的
接下来我们来通过例子
来体会一下
现在我们通过这个例子
来看一下
在构造方法中
如果调用多态的方法
会发生什么
现在我们先声明一个抽象类
Glyph类
这个类里边有一个抽象方法
draw 绘画方法
好 接下来看它的构造方法
大家会看到这点很奇怪
在构造方法中
调用了draw方法
那么draw方法是个抽象方法
没有方法体怎么能调用呢
这一点呢
大家倒不必担心
因为我们是不可能
构造一个Glyph对象的
而构造的对象肯定是
实现了Glyph类的另外一个
非抽象子类的对象
那么这个draw方法呢
它是一个多态方法
所以真正构造哪个子类对象的时候
我们调用的draw方法
会是那个子类的draw方法
所以它的方法体肯定是能找到的
但是是不是就没有问题了呢
这个例子就是为了测试这个问题
所以在调用draw之前
我们输出一个信息
这是调试信息
before draw
调用draw方法之后呢
再输出一条调试信息after draw
接下来声明一个RoundGlyph方法
继承Glyph方法
这个类不再是抽象类了
看 它实现了draw方法
有自己的实现方式
在这儿我们模拟
输出一个radius半径值
模拟绘图了
在这个RoundGlyph里面呢
定义了radius这么一个变量
默认的初始值设为1
然后在它的构造方法中呢
又会用参数值
再去初始化这个radius
接着输出一下
刚刚被初始化过的这个半径值
好
接下来下面这是测试代码
我们在这里构造一个
RoundGlyph对象
仅此而已
看看会发生什么
当我们构造RoundGlyph对象的时候
肯定要找到这个构造方法来执行
我们知道在一个构造方法中
应该第一句就是调用
它超类的构造方法
像这样如果我们没有写
对超类构造方法的调用呢
那么就会调用超类里面
不要参数的
无参数的构造方法
那就是这儿
在这个方法中输出了一行
before draw以后呢
就去调用draw方法
这个时候调用的是
哪个类的draw方法呢
那么要看你正在构造的
是哪个类的对象
我们正在构造的是RoundGlyph对象
所以就调用了
RoundGlyph类的构造方法
输出一个半径
那么现在问题来了
输出的这个半径值会是什么呢
有同学可能估计
那应该是这个默认的1吧
我们看一下输出结果
在第一次输出radius的时候
radius是0
为什么呢
因为在这里调用draw方法的时候
这个新对象还没构造好呢
还没来得及初始化呢
所以在这个时候
你就要使用它的变量
那么就是那个
没有初始化时候的默认值
那是什么呢
数值型的数据
没有初始化的话
默认值是0
所以只是输出了一个0
然后接下来我们看
输出了after draw这个信息以后
就完成了超类Glyph的构造方法
那么就进到RoundGlyph的
构造方法中来了
这个时候会用参数值
给radius赋值初始化
那么参数值是5
把5赋给它了
这时候再输出半径的话
我们看到半径是5
那么通过这个例子说明什么问题呢
要说明的问题就是说
你在构造方法中
调用了一个多态方法
那么在构造对象的时候
这个对象还没有完整的初始化好
你就调用对象的方法
去用这个对象的数据
那显然它的结果是很意外的
所以不要在构造方法中
去调用其他的多态方法
通过这个例子呢
相信大家已经体会到了
在实现构造方法的时候呢
要注意这样几点
首先要尽可能用少的动作
把对象的状态设置好
也就是说构造方法
就是用来初始化的
除了初始化以外
尽量别干别的事儿
如果可以避免呢
就不要调用任何方法
如果说一个对象的构造的
初始化的步骤太复杂了
确实去需要调用一些其他的
辅助的方法
那么这个时候在构造方法内
唯一能够安全调用的
就是在超类中
具有final属性的那些方法
当然也是由于private的私有方法
因为private方法呢
自动就具有final属性
因为final方法是不具有多态性的
是不能够被覆盖的
那么调用final方法
就不会出现前面例子中
那些潜在的问题
在这一节中
我们了解了在构造子类对象的时候
子类和超类
以及它再上级这些超类
这些类的构造方法
它们的调用次序
以及如果在构造方法中
去调用多态方法的时候
会有什么样的隐患
好 这一节内容就是这样
-1.0-导学
--1.0-导学
-1.1-Java与面向对象程序设计简介
--第一章 Java语言基础知识--1.1-Java与面向对象程序设计简介
-1.2-基本数据类型与表达式
-第一章 Java语言基础知识--1.2-基本数据类型与表达式
-1.3-数组
--1.3.1-数组
-第一章 Java语言基础知识--1.3-数组
-1.4-算法的流程控制
--第一章 Java语言基础知识--1.4-算法的流程控制
-1.5-第一章小结
-第一章编程练习题
-课件
--外部链接
-Java环境配置、Eclipse使用、Helloworld程序详解
--使用eclipse建立Java项目、编写和运行Java程序
-Java数据类型
--Java整数类型
--Java浮点类型
--数据类型实战
--数据类型转换
--Java强制类型转换精度损失示例与表达式中的数据类型转换
-Java数组
-Java变量
--Java的变量
-命令行参数
--命令行参数的介绍
-2.0-导学
--2.0-导学
-2.1-面向对象方法的特性
--第二章 类与对象--2.1-面向对象方法的特性
-2.2-1-类声明与对象创建
--第二章 类与对象--2.2-1-类声明与对象创建
-2.2-2-数据成员
--第二章 类与对象--2.2-2-数据成员
-2.2-3-方法成员
--第二章 类与对象--2.2-3-方法成员
-2.2-4-包
--2.2-4-包
--第二章 类与对象--2.2-4-包
-2.2-5-类的访问权限控制
--第二章 类与对象--2.2-5-类的访问权限控制
-2.3-1-对象初始化
--第二章 类与对象--2.3-1-对象初始化
-2.3-2-内存回收
--第二章 类与对象--2.3-2-内存回收
-2.4-枚举类
--2.4-枚举类
--第二章 类与对象--2.4-枚举类
-2.5-应用举例
--2.5-应用举例
-2.6-第2章小结
-第二章编程练习题
-课件
--第二章课件
-3.0-导学
--3.0-导学
-3.1.1-3.1.2-类继承的概念和语法
--第三章 类的重用--3.1.1-3.1.2-类继承的概念和语法
-3.1.3-隐藏和覆盖
--第三章 类的重用--3.1.3-隐藏和覆盖
-3.2-Object 类
--第三章 类的重用--3.2-Object 类
-3.3-终结类与终结方法
--第三章 类的重用--3.3-终结类与终结方法
-3.4-抽象类
--3.4-抽象类
--第三章 类的重用--3.4-抽象类
-3.5-泛型
--3.5-泛型
--第三章 类的重用--3.5-泛型
-3.6-类的组合
--3.6-类的组合
-3.7-小结
--3.7-小结
-第三章编程练习题
-课件
--课件
-4.0-导学
--导学
-4.1-接口
--接口
--第四章 接口与多态--4.1-接口
-4.2.1-4.2.2-类型转换
--类型转换
--第四章 接口与多态--4.2.1-4.2.2-类型转换
-4.2.3-方法的查找
--方法的查找
--第四章 接口与多态--4.2.3-方法的查找
-4.3-多态的概念
--多态的概念
--第四章 接口与多态--4.3-多态的概念
-4.4-多态的应用举例
--多态的应用举例
--第四章 接口与多态--4.4-多态的应用举例
-4.5-构造方法与多态性
--构造方法和多态性
--第四章 接口与多态--4.5-构造方法与多态性
-4.6-本章小结
--本章小结
-第四章编程作业
-课件
--课件
-5.0-导学
--5.0-导学
-5.1.1-5.1.2-异常处理的概念
--第五章 输入输出--5.1.1-5.1.2-异常处理的概念
-5.1.3-5.1.5-异常的处理
--第五章 输入输出--5.1.3-5.1.5-异常的处理
-5.2-输入输出流的概念
--输入输出流的概念
--第五章 输入输出--5.2-输入输出流的概念
-5.3.1-写文本文件
--写文本文件
--第五章 输入输出--5.3.1-写文本文件
-5.3.2-读文本文件
--读文本文件
--第五章 输入输出--5.3.2-读文本文件
-5.3.3-写二进制文件
--写二进制文件
--第五章 输入输出--5.3.3-写二进制文件
-5.3.4-读二进制文件
--读二进制文件
-5.3.5-File类
--File类
-5.3.6-处理压缩文件
--处理压缩文件
-5.3.7-对象序列化
--对象序列化
-5.3.8-随机文件读写
--随机文件读写
-5.4-本章小结
--本章小结
-课件
--课件
-6.0-导学
--导学
-6.1-Java集合框架介绍
--第六章 对象群体的组织--6.1-Java集合框架介绍
-6.2-主要接口及常用的实现类
--第六章 对象群体的组织--6.2-主要接口及常用的实现类
-6.3-常用算法
--常用算法
-6.4-数组实用方法
-6.5-基于动态数组的类型(Vector, ArrayList)
--基于动态数组的类型(Vector, ArrayList)
-6.6-遍历Collection
-6.7-Map接口及其实现
-6.8-第6章小结
--第6章小结
-课件
--课件
-7.0-导学
--导学
-7.1-绘图
--绘图
-7.2-Swing基础
--Swing基础
-7.3-Swing的层次
--Swing的层次
-7.4-布局管理
--布局管理
-7.5-内部类
--内部类
-7.6-事件处理的基本概念
-7.7-事件派发机制
--事件派发机制
-7.8-顶层容器
--7.8-顶层容器
-7.9-中间层容器(一)
-7.10-中间层容器(二)
-7.11-原子组件(一)
-7.12-原子组件(二)
-7.13-原子组件(三)
-7.14-其它Swing特性
-7.15-第7章小结
-课件
--课件