1、1,第8章,继承、抽象类和接口,2,通过本章的学习,主要掌握以下知识点:类的继承 子类的创建 调用父类中特定的构造方法 在子类中访问父类的成员 覆盖抽象类 接口 内部类与匿名类 包,3,本章的重点:类的继承覆盖抽象类 接口 本章的难点:内部类与匿名类,4,8.1 类的继承,类的继承是面向对象程序设计的一个重要特点,通过继承可以实现代码的复用,被继承的类称为父类或超类(superclass),由继承而得到的类称为子类(subclass)。一个父类可以同时拥有多个子类,但由于Java中不支持多重继承,所以一个类只能有一个直接父类。,5,在Java语言中有一个称为java.lang.Object的特
2、殊类,所有的类都是直接或间接地继承该类而得到的。,6,通过在类的声明时使用extends关键字来创建一个类的子类,其格式如下: class SubClass extends SuperClass 把SubClass声明为类SuperClass的直接子类,如果SuperClass又是某个类的子类,则SubClass同时也是该类的间接子类。,8.1.1 子类的创建,7,如果没有extends关键字,则该类默认为java.lang.Object类的子类。因此,在Java中所有的类都是通过直接或间接地继承java.lang.Object类得到的。所以在此之前的所有例子均是java.lang.Objec
3、t类的子类。,8,一、子类的构建方法 【例8.1】类的继承,创建个人类Person,再以该类为父类创建一个学生子类Student,/app8_1.java 继承的简单例子 class Person /Person类是java.lang.Object类的子类 private String name; /name表示姓名private int age; /age表示年龄public Person() /定义无参构造方法System.out.println(“调用了个人构造方法Person()”);public void SetNameAge(String name, int age)this.na
4、me=name;this.age=age;,9,public void show()System.out.println(“姓名:“+name+” 年龄:”+age); class Student extends Person /定义Student类,继承自Person类 private String department;public Student() / Student的构造方法System.out.println(“调用了学生构造方法Student()”);,【例8.1】续,10,public void SetDepartment(String dep)department=dep;S
5、ystem.out.println(“我是”+department +”的学生”); public class app8_1 /主类 public static void main(String args )Student stu=new Student(); /创建Student对象stu.SetNameAge(“张小三”,21);/调用父类的SetNameAge()方法stu.show(); /调用父类的show()方法stu.SetDepartment(“计算机系”); /调用子类的SetDepartment方法 ,【例8.1】续,11,程序执行的结果为: 调用了个人构造方法Person
6、() 调用了学生构造方法Student() 姓名:张小三 年龄:21 我是计算机的学生,【例8.1】续,12,说明: 1通过extends关键字,可将父类的成员继承给子类。在使用这些继承过来的成员时,可利用过去惯用的语法即可,如第38和39行均是利用子类所产生的stu对象,调用从父类继承而来的方法。 2Java在执行子类的构造方法之前,会先自动调用父类中没有参数的构造方法,其目的是为了帮助继承自父类的成员做初始化的操作。 3在严格意义上说,构造方法是不能被继承的,例如父Person有一个构造方法Person(String,int),不能说子类Student也自动有一个构造方法Person(St
7、ring,int),但这并不意味着子类不能调用父的构造方法。,13,二、调用父类中特定的构造方法,通过例8.1可知,即使没有明确地指定构造方法,子类还是会先调用父类中没有参数的构造方法,以便进行初始化的操作。但如果父类中有多个构造方法时,如何才能调用父类中某个特定的构造方法呢。其作法就是在子类的构造方法中通过super()来调用父类特定的构造方法。下面举例来说明。见教材例8.2,14,8.1.2 在子类中访问父类的成员,使用super不但可以访问父类的构造方法,还可以访问父类的成员变量和成员方法,但super不能访问在子类中添加的成员。访问父类成员的格式如下: super. super.,【例
8、8.3】在子类中访问父类的成员。 代码见教材,15,8.1.3 覆盖,覆盖(Overriding)的概念与方法的重载相似,它们均是Java“多态”(Polymorphism)的技巧之一。重载的概念已在前一章中介绍过,重载(Overloading)是指在同一个类内定义名称相同,但参数个数或类型不同的方法,因此Java可根据参数的个数或类型的不同来调用相应的方法。而覆盖(Overriding)则是指在子类中,定义名称、参数个数与类型均与父类相同的方法,用以重写父类里同名方法的功能。,16,一、覆盖父类的方法,子类在重新定义父类已有的方法时,应保持与父类完全相同的方法头声明,即应与父类有完全相同的方
9、法名、返回值和参数类型列表。,17,二、用父类的变量访问子类的成员,通过父类对象也可以访问子类成员。 方法见教材【例8.5】利用父类对象调用子类中成员。,18,8.1.4 不可被继承的成员与最终类,如果父类的成员不希望被子类的成员所覆盖可以将它们声明为final。如果用final来修饰成员变量,则说明该成员变量是最终变量,即常量,程序中的其他部分可以访问,但不能修改。,19,/app8_6.java 父类中的final方法不允许覆盖 class AAA static final double pi=3.14; /声明静态常量public final void show() /声明最终方法Sys
10、tem.out.println(“pi=“+pi); class BBB extends AAA private int num=100;public void show() /错误,不可覆盖父类的方法System.out.println(“num=“+num); ,【例8.6】父类中被声明为final的成员不可被继承。,20,public class app8_6 public static void main(String args )BBB ex=new BBB();ex.show(); ,【例8.6】续,21,8.1.5 Object类,在Java语言中有一个特殊类Object,该类是
11、java.lang类库里的一个类,所有的类都是直接或间接地继承该类而得到的。,22,8.2 抽象类,在Java中可以创建专门的类来做为父类,这种类被称为“抽象类”(Abstract class)。抽象类有点类似“模板”的作用,其目的是根据它的格式来创建和修改新的类。,23,8.2.1 抽象类与抽象方法,定义抽象类的语法格式如下: abstract class 类名 声明成员变量;返回值的数据类型 方法名(参数表)abstract返回值的数据类型 方法名(参数表); ,24,8.2.2 抽象类的应用,由于抽象类的目的是要根据它的格式来创建新的类,所以抽象类里的抽象方法并没有定义处理数据的方法体,
12、而是要保留给由抽象类派生出的新类来定义。 抽象类的应用见教材【例8.10】抽象类的应用举例。,25,8.3 接口,接口(Interface)是Java所提供的另一种重要功能,它的结构与抽象类非常相似。接口本身也具有数据成员与抽象方法。,26,8.3.1 接口的定义,接口定义的语法格式如下: public interface 接口名称 extends 父接口名列表 publicstaticfinal 数据类型 成员变量名=常量; publicabstract 返回值的数据类型 方法名(参数表); ,27,8.3.2 接口的实现与引用,在声明一个类的同时用关键字implements来实现一个接口。
13、接口实现的语法格式为:class 类名称 implements 接口名表 ,28,一个类要实现一个接口时,应注意以下问题: 1非抽象类中不能存在抽象方法。 2一个类在实现某接口的抽象方法时,必须使用完全相同的方法头。 3接口中抽象方法的访问控制修饰符都已指定为public,所以类在实现方法时,必须显示地使用public修饰符。 接口应用例子见教材【例8.11】利用接口建造类。,29,8.3.3 接口的继承,与类相似,接口也有继承性。定义一个接口时可通过extends关键字声明该新接口是某个已存在的父接口的派生接口,它将继承父接口的所有变量与方法。与类的继承不同的是,一个接口可以有一个以上的父接
14、口,它们之间用逗号分隔,形成父接口列表。 接口继承例子见教材【例8.12】接口的继承 。,30,8.3.4 利用接口实现类的多重继承,所谓多重继承,是指一个子类可以有一个以上的直接父类,该子类可以继承它所有直接父类的成员。Java虽不支持多重继承,但可利用接口来实现比多重继承更强的功能。 一个类实现多个接口时,在implements子句中用逗号分隔。 利用接口实现类的多重继承见教材【例8.13】,31,8.4 内部类与匿名类,内部类(Inner Class)是定义在类中的类,内部类的主要作用是将逻辑上相关的类放到一起;而匿名类(Anonymous Class)是一种特殊的内部类,它没有类名,在
15、定义类的同时,就生成该类的一个实例,由于不会在其他地方用到该类,所以不用取名字。,32,8.4.1 内部类,内部类是包含在类中的类,所以内部类也称为“嵌套类”,包含内部类的类又称为“外部类”。其实内部类可以看作是外部类的一个成员,所以内部类也称为“成员类”。,33,/Group.java 内部类与外部类的访问规则内部类外部类 public class Group private int age; /声明外部类的私有成员变量public class Student /声明内部类String name; /声明内部类的成员变量public Student(String n,int a) /定义内部
16、类的构造方法name=n; /访问内部类的成员变量nameage=a; /访问外部类的成员变量agepublic void output() /内部类的成员方法System.out.println(“姓名:”+this.name+”;年龄:”+age);,【例8.14】内部类与外部类的访问规则。,34,public void output() /定义外部类的成员方法Student stu=new Student(“刘 洋”,24); /创建内部类对象stustu.output(); /通过stu调用内部类的成员方法public static void main(String args)Grou
17、p G=new Group();G.output(); ,【例8.14】续,程序运行结果如下: 姓名:刘 洋;年龄:24,35,8.4.2 匿名内部类,所谓匿名内部类(anonymous inner class),是指可以利用内部类创建没有名称的对象,并利用它访问到类里的成员。,36,创建匿名内部类并访问成员的语法格式如下: ( /创建匿名内部类,并执行所定义的方法new 类名() /括号“()”内不允许有参数方法名(参数1,参数2,参数n)方法体语句; ).方法名(参数1,参数2,参数n); 匿名内部类的使用方法见教材【例8.16】,37,8.5 包,java中引如了包(package)的概
18、念来管理类名空间。就像文件夹把各种文件组织在一起,使硬盘更清晰、有条理一样,Java中的包把各种类组织在一起,使得程序功能清楚、结构分明。,38,8.5.1 包的概念,所谓包就是Java提供的一种区别类名空间的机制,是类的组织方式,包对应一个文件夹,包中还可以再有包,称为包等级。,39,8.5.2 使用package语句创建包,若要创建自己的包,就必须以package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包,它的格式为: package 包名1.包名2.包名3;,40,8.5.3 Java中的常用包,Java的常用包有:,41,8.5.4 利用import语句引用Jav
19、a定义的包,如果要使用Java包中的类,必须在源程序中用import语句导入所需要的类。import语句的格式为: import . .|* 其中import是关键字,.表示包的层次,与package语句相同,它对应于文件夹。,42,8.6 Java的垃圾回收,垃圾回收(Garbage-collection)是Java提供的一种自动内存回收功能,可以让程序员减轻许多内存管理的负担,也减少程序员犯错的机会。 当一个对象被创建时,Java虚拟机JVM会为该对象分配一定的内存、调用该对象的构造方法并开始跟踪该对象。当该对象停止使用时,JVM将通过垃圾回收器回收该对象所占用的内存。那么,Java是如何知道一个对象是无用的呢?这是因为系统中的任何对象都有一个引用计数器,一个对象被引用1次,则该对象的引用计数器为1,被引用2次,则引用计数器为2,依次类推,当一个对象的引用计数器减到0时,说明该对象可以回收。,43,再见!,