1、目录任务一 搭建环境(构建Java集成开发环境)任务二 Java欢迎你(开发简单Java应用程序任务三 小试牛刀(学习Java语言基础)任务四 挑战选择(使用分支控制流程)任务五 游戏人生(使用循环控制流程)任务六 回归自然(创建、使用类和对象)任务七 3G时代的消息传递(定义和使用类方法)任务八 保护你的隐私(封装的使用)任务九 子承父业(继承和多态的使用)任务十 上帝万能之手(接口的使用)任务十一 用数组存储信息(使用数组)任务十二 使用字符串进行交流(使用字符串)任务十三 防患于未然(捕获并处理异常)任务十四 主动出击(抛出异常)任务十五 认识Java Applet(Applet入门)任
2、务十六 丰富多彩的Applet(在Applet中播放声音和显示图像)任务十七 进入Windows世界(设计图形用户界面)任务十八 布局规划(使用布局管理器)任务十九 事件委托处理(如何处理事件)任务二十 选择之道(使用选择控件和选择事件)目录任务二十一 简明清晰的菜单(使用菜单和其他常用事件)任务二十二 访问数据(使用JDBC连接数据库)任务二十三 访问数据升级(数据库编程)任务二十四 文件管理(目录与文件管理)任务二十五 顺序进出之道(文件的顺序访问)任务二十六 随机进出之道(文件的随机访问)任务二十七 JAVA的分身术(创建和启动线程)任务二十八 线程的生命周期与优先级(线程的状态与调度)
3、任务二十九 基于连接的通信(Java中的套接字Socket)任务三十 基于无连接的通信(Java中的数据报编程)目录任务九 子承父业(继承和多态的使用)21知识目标知识目标能力目标能力目标继承的概念;继承关键字;父类与子类之间的关系,super关键字。多态的概念;静态多态,动态多态;多态的实现。最终类和抽象类。掌握继承的实现;掌握super关键字;掌握多态的实现。内容提要内容提要4跟我做:跟我做:汽车的分类关系汽车的分类关系 1235实现方案实现方案 代码分析代码分析 必备知识必备知识 动手做一做动手做一做 9.1 跟我做:汽车的分类关系 n任务情景任务情景汽车是一般的交通工具,具有车类型、品
4、牌、引擎数量、外观颜色等属性,能够发动、加速、刹车、停车等功能。汽车又可分为公共汽车、出租车、卡车等。公共汽车具有自己的第几路编号、最大载客数量属性,能够报站。出租车具有所属公司、最大载客数量属性,能够给乘客打发票。卡车具有最大载重量属性,能够卸货。请编写Vehicle汽车类、Bus公共汽车类。Taxi类和Truck类待学完本任务后自行完成。n运行结果运行结果第1章目录n问题分析问题分析回忆任务六中定义类的三个步骤,先定义类名,再编写类的属性,最后编写类的方法。本任务采用这三个步骤,编写好代码后,我们很快就会发现,Vehicle汽车类和Bus公共汽车类出现了许多相同的语句代码。在属性方面,都包
5、含了车类型、品牌、引擎数量、外观颜色重复的信息定义,在功能上都有发动、加速、刹车、停车等重复的行为定义。汽车、公共汽车的成员变量和成员方法对照请见图9-2。现在,我们换个思路考虑。汽车是一般性的概念,它包含的成员变量和成员方法,在公共汽车、出租车、卡车中也具有,因为公共汽车是一种汽车,出租车、卡车也是一种汽车,只不过公共汽车、出租车、卡车是一种更具体的汽车,除了汽车的公共特性外,还有自己的特有性质。经过分析,采取如下措施,在定义类时,将公共汽车类、出租车类、卡车类中相同的属性和方法抽象出来,集中放在汽车类中,形成一种共享的机制,公共汽车类、出租车类、卡车类中只放自己特有的成员变量和成员方法,减
6、少重复代码。这样的汽车类称为父类,公共汽车类、出租车类、卡车类称为子类。子类继承父类的非私有成员变量和成员方法。第1章目录9.2 实现方案 n解决步骤解决步骤1.打开Eclipse,在study项目中创建包com.task09,再确定类名Vehicle,得到类的框架。package com.task09;public class Vehicle2.然后,进行类的属性描述,只输入抽象出来的共有的成员变量Stringtype;String brand;int engineNum;String color;3.接着,定义类的构造方法:public Vehicle()public Vehicle(St
7、ring type,String brand,int engineNum,String color)4.再定义抽象出来的共有的方法:/发动、加速、刹车、停车public void start()public void accelerate()public void brake()public void stop()9.2 实现方案 5.定义Bus类。Bus类作为更具体的子类,只定义自己特有的性质。父类Vehicle类已有的成员变量和成员方法不再定义。public class Bus extends Vehicle/加上extends关键字和父类名Vehicle/公共汽车具有自己的最大载客数量、
8、第几路编号属性int maxLoad;/特有的成员变量特有的成员变量String busNo;/*构造方法*/public Bus()public Bus(int maxLoad,String busNo)/报站public void announceBusStop()/特有的成员方法特有的成员方法6.定义VehicleTest测试类,运行程序。对Vehicle类、Bus类的继承关系进行测试,Bus类能否访问父类的成员变量,能否调用父类的成员方法。Bus bus=new Bus(子类公共汽车,女神,2,白色,50,9路);bus.start();/调用父类的成员方法bus.announceBu
9、sStop();/公共汽车报站9.2 实现方案 n程序代码程序代码见书上源码第1章目录9.3 代码分析 9.3 代码分析 n应用扩展应用扩展Bus类继承了Vehicle类后,在发动、加速、刹车、停车功能上加上自己的特性,就要重写这四个方法。重写形成了多态。Bus类升级新增方法如下:/发动、加速、刹车、停车public void start()System.out.println(type+busNo+brand+engineNum+引擎+color+汽车发动);public void accelerate()System.out.println(type+busNo+brand+engineN
10、um+引擎+color+汽车加速);public void brake()System.out.println(type+busNo+brand+engineNum+引擎+color+汽车刹车);public void stop()System.out.println(type+busNo+brand+engineNum+引擎+color+汽车停车);第1章目录9.4 必备知识 9.4.1 类的继承1.继承的概念继承的概念由一个已有类定义一个新类,称为新类继承了已有类。已有类称为父类,新类称为子类。例如,汽车类是父类,公共汽车类、出租车类、卡车类是子类。通过子类继承父类,子类具有父类的一般特性
11、,包括非私有的属性和行为。子类还可以增加自身特性,定义新的属性和行为,甚至可以重新定义父类中的属性和方法,扩展类的功能。例如,汽车类具有车类型、品牌、引擎数量、外观颜色,能够发动、加速、刹车、停车等一般特性。作为子类的公共汽车类、出租车类、卡车类继承了父类的这些特性,另外,新增了自己的特性,公共汽车具有自己的第几路编号、最大载客数量属性,能够报站。出租车具有所属公司、最大载客数量属性,能够给乘客打发票。卡车具有最大载重量属性,能够卸货。公共汽车类还重新定义了父类的发动、汽车公共汽车出租车卡车加速、刹车、停车功能。第1章目录汽车公共汽车出租车卡车图9-2 汽车又可分为公共汽车、出租车、卡车 怎样
12、判断类与类之间具有继承关系呢?汽车具有一般特性,公共汽车、出租车、卡车是一种是一种汽车,具有更具体的特性,符合is-a关系。根据这种原则,确定汽车是父类,公共汽车、出租车、卡车是子类。父类更通用、子类更具体父类更通用、子类更具体。再看一看人、消费者和经销商关系。人具有姓名、年龄属性,能够说话。消费者、经销商是一种是一种人,具有姓名、年龄属性,能够说话。消费者还能够购物、付费,经销商能够进货、收费,具有更具体的特性。符合is-a关系。所以,人是父类,消费者和经销商是子类。第1章目录9.4 必备知识必备知识 2.继承的意义继承的意义在定义汽车类、公共汽车类、出租车类、卡车类时,通过分析了解到,汽车
13、类和其他车类之间的重复代码太多,具有许多相同的成员变量和成员方法,既增加了程序员的工作量,降低编程效率,也违背了Java语言的“write once,only once”的原则。如果把所有子类中相同的代码都抽取到父类中,建立继承关系,让子类自动继承父类的属性和方法,那么子类中就省去重复代码。例如,在汽车类、公共汽车类、出租车类、卡车类建立了继承关系后,公共汽车类、出租车类、卡车类中相同的代码,包括成员变量定义和方法的定义,抽取到汽车类中,子类中不再进行重复定义,程序的有效实现代码得到复用。因此,使用继承提高代码的复用性。9.4 必备知识必备知识 3.继承的实现继承的实现继承的实现分两个步骤:定
14、义父类父类可以是系统类,也可以是自定义类。如果是系统类,该步骤可以省略。在父类中只定义一些通用的属性与方法,例如:Vehicle汽车类只定义了车类型、品牌、引擎数量、外观颜色属性,以及发动、加速、刹车、停车行为。Stringtype;/车类型、品牌、引擎数量、外观颜色属性String brand;int engineNum;String color;public void start()/发动、加速、刹车、停车行为public void accelerate()public void brake()public void stop()9.4 必备知识必备知识 定义子类子类定义格式:类修饰符 c
15、lass 子类名 extends 父类名父类名extends关键字表示一个类继承了另一个类。例如,Bus公共汽车类继承Vehicle汽车类。public class Bus extends Vehicle/父类名只能有一个然后,定义子类特有的成员变量和成员方法。例如,Bus公共汽车类作为子类,新增了自己的特性。int maxLoad;/子类特有的属性String busNo;public void announceBusStop()/报站,子类特有的方法System.out.println(busNo+公共汽车报站);注意:注意:一个子类只能继承一个父类,即单继承单继承。但一个父类可以有多个子
16、类。9.4 必备知识必备知识 改错:改错:下面继承定义有哪些错误?/*人(Person)具有姓名(name)、年龄属性(age),能够说话(talk)。*消费者(Customer)具有姓名(name)、年龄属性(age),能够说话(talk),还能够购物(shop)。*/public class Person String name;int age;public void talk()System.out.println(name+说话);public class person extends Customer,Shop String name;public void talk()System
17、.out.println(name+说话);private void shop()System.out.println(name+购物);提示:有5个错误。9.4 必备知识必备知识 4.子类与父类的关系子类与父类的关系定义子类之后,父类与子类之间就产生了一些特殊的关系,在代码编写上会受到影响,程序员必须清楚。子类自动继承父类的属性和方法,但不能继承访问权限为private的成员变量和成员方法。例如:父类Vehicle中有一私有成员变量和一私有成员方法:private String color;/父类中私有成员变量private void start()/父类中私有成员方法子类Bus中,按如下方
18、式对父类成员变量和成员方法进行访问,将会出错。color=银灰色;/子类中访问父类中私有成员变量,出错出错start();/子类中调用父类中私有成员方法,出错出错当我们将父类Vehicle中private改为缺省时,子类Bus中访问顺利完成。String color;/父类中private改为缺省void start()/父类中private改为缺省子类中可以定义特定的属性和方法。例如,在子类Bus中,增加售票员(conductor)属性,和开门open()方法:String conductor;void open()9.4 必备知识必备知识 子类中方法重写方法重写。所谓方法重写就是子类定义的
19、方法和父类的方法具有相同的名称、参数列表、返回类型和访问修饰符相同的名称、参数列表、返回类型和访问修饰符。例如,父类Vehicle中有如下方法:public void accelerate()System.out.println(type+brand+engineNum+引擎+color+汽车加速);在子类Bus中,新增自己的加速accelerate()方法,这就是方法重写。public void accelerate()/方法重方法重写写super.accelerate();System.out.println(这是子类Bus中的重写方法);方法重写会隐藏父类的同名方法。也就是说,在子类Bu
20、s中,如果调用accelerate()方法,将不再是调用父类的accelerate()方法,而是子类Bus中的方法。子类的属性与父类的属性相同时,也会出现隐藏的现象。9.4 必备知识必备知识 super关键字与this关键字出现隐藏现象后,如果需要使用父类的成员属性和成员方法,可以通过使用super关键字。例如,在子类Bus中,调用父类的accelerate()方法:super.accelerate();/super指当前对象的父对象如果用this关键字,则表示调用当前对象的accelerate()方法:this.accelerate();/this指当前对象通过使用super关键字与this
21、关键字,可以很显式地区分开调用的是当前对象的成员,还是父对象的成员。另外,当方法体中定义的变量,或方法的形式参数与对象的成员变量名相同,也必须用this关键字指明当前对象的成员变量。9.4 必备知识必备知识 子类的构造方法子类不能继承父类的构造方法,因为父类的构造方法用来创建父类对象,子类需定义自己的构造方法,创建子类对象。子类的构造方法中,通过super关键字调用父类的构造方法。例如,在子类Bus的构造方法中,用如下语句实现了对父类构造方法的调用:super();/调用父类的无参构造方法super(type,brand,engineNum,color);/调用父类的带参构造方法注意:注意:s
22、uper(参数);必须是子类构造方法的第一条语句。如果该语句省略,则会自动调用父类无参构造方法。因为子类创建对象时,先创建父类对象,再创建子类对象。如果需要调用当前类中的构造方法,用this关键字。例如,在子类Bus的构造方法中,用如下语句实现了对当前类中的构造方法的调用:this(40,“8路”);/调用当前类中的带参构造方法9.4 必备知识必备知识 5.根类根类Object在Java 中,所有的类都是通过直接或间接地继承java.lang.Object类得到的,Object类是一切类的祖先,称为根类。当定义类,而没有使用extends关键字时,表示所定义类的父类为Object类,这是Jav
23、a中的一种特别约定。根类Object类的方法如clone()、equals(obj)、finalize()、getClass()、hashCode()、notify()、notifyAll()、toString()、wait()等,子类都可以通过继承,进行调用。关于toString()方法,在任务六的类的定义中,通过重写,已经多次使用了该方法。9.4 必备知识必备知识 9.4.2 类的多态类的多态1.多态的概念多态的概念多态是指一个方法声明的多种实现状态,即在程序中同名的不同方法共存,调用者只需要使用同一个方法名,系统会根据不同情况,调用相应的方法,从而实现不同的功能。简而言之,多态性即“一个
24、名字,多个方法”。例如,父类Vehicle中有如下方法:public void accelerate()在子类Bus中,也有accelerate()方法:public void accelerate()/方法重写在程序中同名的不同方法共存,形成了多态。2.多态的意义多态的意义在面向对象程序设计中,多态是具有表现多种形态的能力的特征,有时需要利用方法的重名,提高程序的抽象度和简洁性,以及程序的可扩展性及可维护性。例如使用多态之后,当需要增加新的子类PoliceCar警车类时,无需更改父类Vehicle,代码得到了扩展,维护起来也方便。9.4 必备知识必备知识 3.多态的分类多态的分类多态分为静态
25、多态和动态多态。静态多态指通过同一个类中的方法重载实现的多态,动态多态指通过类与类之间的方法重写实现的多态。方法重载参见8.4.4。方法重写参见本任务9.4.1 类的继承4.子类与父类的关系 子类中方法重写部分。静态多态是编译时多态,指程序会根据参数的不同来调用相应的方法,具体调用哪个被重载的方法,由编译器在编译阶段静态决定。动态多态是运行时多态,指在运行时根据调用该方法的实例的类型来决定调用哪个重写方法。静态多态对程序运行更有效率,动态多态更具有灵活性。4.多态的实现多态的实现多态通过给同一个方法定义几个版本来实现的。例如,现有三个类,Grandfather类是Father类的父类,Fath
26、er类是Child类的父类。三个类的代码如下:9.4 必备知识必备知识 package com.task09;/*Grandfather.java *多态,本类作为Father的父类*/public class Grandfather int i;int j;/*param i*param j*/public Grandfather(int i,int j)this.i=i;this.j=j;int smoke()System.out.println(Grandfather的方法smoke():);return i+j;9.4 必备知识必备知识 package com.task09;/*Fat
27、her.java *多态,本类作为Grandfather的子类,本类作为Child的父类*/public class Father extends Grandfather/*param i*param j*/public Father(int i,int j)super(i,j);int drink()System.out.println(Father的方法drink():);return 0;9.4 必备知识必备知识 package com.task09;/*Child.java *多态,本类作为Father的子类*/public class Child extends Father/*pa
28、ram i*param j*/public Child(int i,int j)/子类的构造方法super(i,j);/调用父类的构造方法int drink()/重写了父类的方法System.out.println(Child重写的方法drink():);return i*j;package com.task09;public class GrandfatherTest/*param args*/public static void main(String args)/创建子类的对象子类的对象,赋给父类对象变量父类对象变量fatherFather father=new Child(3,4);/
29、调用子类子类Child重写重写的drink()方法System.out.println(father.getClass()+喝水杯数+father.drink();/调用父类父类Grandfather的smoke()方法(子类未重写子类未重写)System.out.println(father.getClass()+抽烟支数+father.smoke();9.4 必备知识必备知识 多态程序运行结果见图9-3。在GrandfatherTest测试类中,首先声明Father类型的变量father,然后建立Father类的子类Child类的一个实例,并把引用存储到father中。Java运行时,系统
30、分析该引用是Child类型的一个实例,因此调用子类Child重写的drink()方法。因为方法smoke()未被子类Child重写,所以运行时系统调用继承的父类Father的父类Grandfather的smoke()方法。注意:注意:因为子类通过继承具备了父类的所有属性(私有属性除外),所以,凡是要求使用父类对象的地方,都可以用子类对象来代替。对子类的一个实例,运行时系统到底调用哪一个方法呢?如果子类重写了父类的方法,则调用子类的方法;如果子类未重写父类的方法,则调用父类的方法。因此,父类对象可以通过引用子类的实例调用子类的方法。9.4 必备知识必备知识 改错:改错:下面关于多态定义有哪些错误
31、?父类Grandfather中有如下方法:int smoke()System.out.println(Grandfather的方法smoke():);return i+j;子类Father中定义了方法:int smoke(int i)System.out.println(Father的方法smoke():);return i+j;提示:有1个错误。9.4 必备知识必备知识 9.4.3 最终类和抽象类1.最终类最终类当一个类的定义使用了final关键字时,该类称为最终类。最终类不能有子类,也就是不能被继承不能被继承。一般,用来完成某种标准功能的类,例如,系统类String、Byte和Double
32、,或定义已经很完美,不需要生成子类的类,通常定义为最终类。最终类的声明格式:final class 类名2.抽象类抽象类当一个类的定义使用了abstract 关键字时,该类称为抽象类。抽象类是供子类继承却不能创建实例不能创建实例的类。抽象类中可以声明只有方法头没有方法体的抽象方法抽象方法,方法体由子类实现。抽象类提供了方法声明与方法实现分离的机制,使各子类表现出共同的行为模式。抽象方法在不同的子类中表现出多态性。抽象类的声明格式:public abstract class 类名9.4 必备知识必备知识 在面向对象程序设计时,抽象类一般用于现实世界抽象的概念,例如,食物,水果、交通工具等,我们看
33、不到他们的实例,只能看到他们子类,例如米饭、苹果、飞机等子类的实例。Java中的java.lang.Number类是抽象类,没有实例,它是integer和float具体数字类型的抽象父类。例如,有计算机类Computer和笔记本电脑类Notebook两个类。Computer为抽象类,Notebook为其实现子类。代码如下:9.4 必备知识必备知识 package com.task09;/*Computer.java *抽象类抽象类,本类作为Notebook的父类*/public abstract class Computer/抽象类的定义要有abstract关键字关键字String brand
34、;/成员变量abstract void showBrand();/抽象方法抽象方法,没有方法体没有方法体package com.task09;/*Notebook.java *实现类,本类作为Computer的实现子类*/public class Notebook extends Computer Overridevoid showBrand()/实现实现抽象方法brand=Dell;System.out.println(品牌:+brand);9.4 必备知识必备知识/*param args*/public static void main(String args)Computer compu
35、ter=new Notebook();/子类的对象赋给抽象类的变量computer.showBrand();9.4 必备知识必备知识 改错:改错:下面关于抽象类有哪些错误?public abstract class Food private int status=0;int getStatus()return status;class Egg extends Foodpublic class FoodTest()public static void main(String args)Food food=new Food();food.getStatus();提示:有1个错误。牢记抽象类、抽象方
36、法的定义和使用要求。9.4 必备知识必备知识 9.5 动手做一做动手做一做一、实训目的掌握继承的概念和实现;掌握多态的概念和实现。二、实训内容编写动物世界的继承关系代码。动物(Animal)包括山羊(Goat)和狼(Wolf),他们吃(eat)的行为不同,山羊吃草,狼吃肉,但走路(walk)的行为是一致的。通过继承实现以上需求,并编写AnimalTest测试类进行测试。三、简要提示山羊类和狼类具有共同的吃、走路行为,应该抽象出来,放在动物类中。但山羊吃草,狼吃肉,具体吃的行为各不相同,所以,在山羊类和狼类中要重写吃行为。四、程序代码参见本教材教学资源。五、实训思考1.继承如何实现?2.方法重写如何实现?3.理解测试类中的调用方法过程。