1、第二部分 Java语言基础篇,第4章 Java语言与面向对象,(之二),学习目的,学习了解面向对象编程特点,理解面向对象的基本概念以及Java系统对类与对象概念的实现,从而能进一步掌握面向对象的程序开发技术。 在深入学习过程中,学习Java语言重要的继承特征;理解和掌握面向对象系统中的接口技术;并能学会熟练使用系统提供的类包等技术。,主要内容,Java语言的类和对象Java类的继承与封装 Java语言的接口和包 Java语言的异常处理 【综合案例】 本章小结,4.2 类的继承与封装,继承(Inheritance)就是面向对象程序的两个类之间的一种关系。类继承也称为类派生,是指一个类可以继承其他
2、类的所有内容,包括数据和方法。被继承的类称为父类或者超类(Superclass),继承后产生的类称为子类或派生类(Subclass)。面向对象程序设计允许一个父类,可以同时拥有多个子类,一个子类可以同时继承多个父类,后者称为多重集成。Java不直接支持多重继承,而是使用接口来实现子类从多个父类获取属性和方法。Java通过关键字extends来实现类的继承。,4.2.1【综合案例4-4】,不同类别消费人员购物收费程序。,abstract class Goods /定义抽象类 String goods;float price;double total;int num;public abstract
3、 void goods(String _goods, float _price, int _num);/定义抽象方法 class Common extends Goods /定义子类(一级子类) public void showCommon() System.out.println(“这是一个普通用户“); public void goods(String _goods, float _price, int _num) goods=_goods;price=_price;num=_num;total=_price*_num; /调用父类的变量public void showBuy() Syst
4、em.out.println(“货物:“+goods);System.out.println(“价格:“+price);System.out.println(“数量:“+num);System.out.println(“总价:“+total); ,final class Associator extends Common /定义终结子类(二级子类) public void showAssociator() System.out.println(“这是一个会员用户“); public void showBuy() super.showBuy();System.out.println(“作为会员用
5、户,享受九折优惠“);System.out.println(“总价:“+total*0.9); public class BuyGoods public static void main(String args) Common AA=new Common(); /声明一级子类对象并初始化AA.showCommon(); /调用一级子类内部成员方法AA.goods(“电视机“, 3800, 2); /实例化对象AA.showBuy(); /调用一级子类内部成员方法 Associator BB=new Associator(); /声明二级子类对象并初始化BB.goods(“洗衣机“, 1980,
6、 3); /实例化对象BB.showAssociator(); /调用二级子类内部成员方法BB.showBuy(); /调用一级子类(父类)成员方法 ,程序运行结果:这是一个普通用户货物:电视机价格:3800.0数量:2总价:7600.0这是一个会员用户货物:洗衣机价格:1980.0数量:3总价:5940.0作为会员用户,享受九折优惠总价:5346.0,4.2.2 继承,继承实质上就是从一个类中派生出另一个类,其中前者称为父类,后者称为子类,子类代表父类的一种增强或改进。 1.子类的创建 语法格式:访问修饰符 class 子类名 extends 父类名 成员变量定义成员方法定义,特殊变量thi
7、s 和super,this的使用场合 用来访问当前对象的数据成员,使用形式:this.数据成员 用来访问当前对象的成员方法,使用形式:this.成员方法(参数) 当有重载的构造方法时,用来引用同类的其它构造方法,使用形式:this(参数),特殊变量this 和super,super的使用场合 用来访问直接父类隐藏的数据成员,使用形式:super.数据成员 用来调用直接父类中被覆盖的成员方法,使用形式:super.成员方法(参数) 用来调用直接父类的构造方法,使用形式:super(参数),程序段4-8,class Point /父类声明 protected int x,y;Point(int a
8、,int b) setPoint(a,b);public void setPoint(int a,int b) x=a; y=b; class Line extends Point /子类声明 protected int x,y;Line(int a,int b) super(a,b); /调用父类构造方法setLine(a,b); public void setLine(int x,int y) this.x=x+x; /当前对象的数据运算this.y=y+y; ,特殊变量this和super演示练习,public double length() int x1=super.x, y1=sup
9、er.y; /局部变量取父类数据成员值int x2=this.x, y2=this.y; /局部变量取子类数据成员值return Math.sqrt(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);public String toString() return “直线端点:“+super.x+“,“+super.y+“ “+x+“,“+y+“n直线长度:“+this.length();public class TestPoint public static void main(String args) Line line=new Line(50,50);System.out.pr
10、intln(“n“+line.toString();,程序运行结果:直线端点:50,50100,100直线长度:70.71067811865476,特殊变量this和super演示练习,构造方法的继承,子类无条件地继承,继承父类的不含参数的构造方法;如果子类自己没有构造方法,则它将继承父类的无参构造方法作为自己的构造方法。如果子类自己定义了构造方法,则在创建新对象时,它将先执行继承自父类的无参数构造方法,然后再执行自己的构造方法。对于父类的含参数构造方法,子类可以通过在自己的构造方法中使用super关键字来调用它,但这个调用语句必须是子类构造方法的第一个可执行语句。,父类对象与子类对象的转换,
11、子类对象可被视为是其父类的一个对象;父类对象不能被当作是其某一个子类的对象;如果一个方法的形参是父类的对象,则在调用该方法时,可以使用子类对象作为实参;父类对象引用指向子类对象。,程序段4-9,父类对象引用指向子类对象,class SuperClass /定义父类 int x; class SubClass extends SuperClass /定义子类 int y;char ch; public class UseSuperSub /使用父类与子类 SuperClass sc, sc_ref;SubClass sb, sb_ref;sc=new SuperClass( );sb=new S
12、ubClass( );sc_ref=sb; /父类引用指向子类对象sb_ref=(SubClass)sc_ref; /父类引用转换成子类引用 ,abstract和final,抽象类是包含一个或多个抽象方法的类。 抽象方法是指在抽象类中定义的方法,这些方法只有方法头的声明,而用一个分号来代替方法体的定义,即只定义成员方法的接口形式,而没有具体操作。在各子类继承了父类的抽象方法之后,再分别用不同的语句和方法体来重新定义它,形成若干个名字、返回类型和参数列表相同,目的一致,但具体实现有一定差别的方法。,抽象类的注意事项:(1)凡是用abstract修饰的类为抽象类, 用abstract修饰的方法为抽
13、象方法。 (2)抽象类中可以有一个或多个抽象方法,也可以包含非抽象的方法。 (3)抽象方法的类必须是抽象类,它只能存在于其中。 (4)在抽象类中只能指定抽象方法名及其类型,而不能书写其实现代码。 (5)抽象类可以派生子类,在其子类中必须实现抽象类中定义的所有抽象方法。 (6)抽象类不能创建对象,创建对象由派生子类实现。 (7)若父类中已有某个抽象方法,则子类中就不能有同名的抽象方法。,使用final声明的类则不可有子类。 使用final修饰方法的功能是于内部语句不能被更改的最终方法。,继承的特征总结 (1)子类可以从父类那里继承所有非private的数据 成员和成员方法,以体现其共性; (2)
14、在子类中也可以定义一些自己特有的数据成员和成员方法,以体现其个性; (3)类之间的继承关系呈现为层次结构; (4)继承关系是传递的; (5)出于安全性和可靠性的靠路,Java仅支持单重继承,而使用接口机制来实现多重继承。,4.2.3 多态,多态是指一个类中具有相同名字多个不同方法共存的情况。Java提供了两种多态机制:重载(overload)和覆盖(override)。,1. 重载,重载是指在同一个类中定义多个同名而内容不同的成员方法。即是一种对一个方法进行多次定义的设计方法。这一思想在面向对象程序设计中对所有的成员方法都适用,包括构造方法(不包括析构方法)。,程序段4-10,创建一个显示学生
15、姓名和平均成绩点数(GPA)程序,有四种情况: (1)不知道姓名、GPA的学生对象; (2)知道姓名、不知道GPA的学生对象; (3)不知道姓名、知道GPA的学生对象; (4)知道姓名和GPA的学生对象。,class Student public String name;private double GPA;public Student() /无参构造方法定义 this(“无名氏“,-1.0); public Student(String _name) /有参构造方法定义 this(_name,-1.0); public Student(double _GPA) /有参构造方法定义 this(
16、“无名氏“,_GPA); public Student(String _name, double _GPA)/有参构造方法定义 name=_name;GPA=_GPA;public void showStudent() System.out.println(“Student:“+name);if(GPA=0.0)System.out.println(“(GPA:“+GPA+ “)“);elseSystem.out.println(); ,public class StudentTest public static void main(String args) Student nobody=ne
17、w Student(); /对象声明并初始化Student promise=new Student(“张三“); /对象声明并实例化Student goodStudent=new Student(4.0); /对象声明并实例化Student top=new Student(“李四“); /对象声明并实例化nobody.showStudent(); /对象方法引用promise.showStudent(); /对象方法引用goodStudent.showStudent(); /对象方法引用top.showStudent(); /对象方法引用 ,程序运行结果:Student:无名氏Student:
18、张三Student:无名氏(GPA:4.0)Student:李四,2. 继承的隐藏和覆盖,子类成员的继承是指,子类可以继承父类的所有非私有方法。 子类成员变量的隐藏是指,子类成员变量可继承自己的父类,还可以自己定义成员变量而将父类同名成员变量隐藏。 子类成员方法的覆盖是指,子类使用新的方法来代替父类原有的方法,以提供更完整、功能更强的方法。其做法是在子类中声明一个与父类具有相同名称、相同的参数表和相同的返回类型的方法。,程序段4-11,class Exm4_11 int x; /父类成员变量声明void set(int a) /父类方法成员声明 x=a; void print() System
19、.out.println(“x=“+x); class Exmp extends Exm4_11 int x; /子类成员变量隐藏void set(int a) /子类方法成员覆盖 x=a; void print() System.out.println(“x=“+x+ “ “+super.x); /特殊变量super.使用 ,继承的隐藏与覆盖演示程序,public class Exm4_11Test public static void main(String args) Exm4_11 A=new Exm4_11(); /父类对象声明Exmp B=new Exmp(); /子类对象声明A.
20、set(100); /父类对象成员调用A.print();B.set(30); /子类对象成员调用B.print();B.newprint();System.out.println( “x=“+A.x+ “+(Exm4_11)A).x);System.out.println( “x=“+B.x+ “+(Exm4_11)B).x); ,程序运行结果x=100x=30x=0 30x=100100x=030,4.2.4 【综合案例4-5】,学校学生账单管理应用程序某国外一个州立大学的学生学习缴费系统。因为州内外的学生缴费标准不同,因此分别计费。州内每学分收费为$75,而州外的每学分收费为$180,收
21、费管理账单上包含有学校名称、学生姓名、信用卡使用时间以及账单总额。,abstract class Student protected final static double INSTATE_TATE=75;protected final static double OUTSTATE_TATE=180;protected String name;protected int hours;public abstract void showStudent();public final void showSchoolName()System.out.println(“Java State Univers
22、ity“);System.out.println(“*“); class OutStatesStudent extends Studentpublic OutStatesStudent(String _name, int _hours) name=_name;hours=_hours;public void showStudent() showSchoolName();System.out.println(name+“ takes “+hours+ “ credits“);System.out.println(“OutState bill:“+hours*OUTSTATE_TATE); ,cl
23、ass InStateStudent extends Student public InStateStudent(String _name, int _hours) name=_name;hours=_hours;public void showStudent() showSchoolName();System.out.println(name+ “ takes “+hours+ “ credits“);System.out.println(“InState bill:“+hours*INSTATE_TATE); public class Bursarsoffice public static
24、 void main(String args) InStateStudent resident=new InStateStudent(“John Doe“, 24);OutStatesStudent alien=new OutStatesStudent(“Tom Smith“, 26);resident.showStudent();System.out.println();alien.showStudent(); ,程序运行结果: Java State University * John Doe takes 24 credits InState bill:1800.0 Java State U
25、niversity * Tom Smith takes 26 credits OutState bill:4680.0,4.2.5 封装,封装就是利用抽象数据类型将数据和基于数据的操作封装在一起。 封装主要指的是对象的封装性,即将属于某一类的一个具体的对象封装起来,使其数据和操作成为一个整体。,4.3 Java语言的接口和包,由于Java只支持单重继承,所以程序中的类层次结构易膨胀、庞杂、难以管理和掌握。接口则可实现多重继承的问题。,4.3.1 接口,接口类似于类,它定义类若干个抽象方法和常量,形成一个属性集合,该属性集合通常对应一组功能,其主要作用是帮助实现类之间多重继承的功能。凡是需要实现
26、这种特定功能的类,都可以继承这个属性集合并在类内使用它,这种属性集合就是接口。 把对接口功能的“继承”称为“实现”。,接口的定义public interface 子接口名extends 父接口名列表 /接口体/成员变量声明/抽象方法声明publicabstractnative返回值 方法名(参数列表) throw 异常列表; 一个类只能有一个父类,但它可同时实现多个接口。 注意:所有属性都必须是public、static、final类型;所有方法都必须是public、abstract 的。,程序段4-12,系统定义的接口DataInput定义语句,public interface java.i
27、o.DataInput public abstract boolean readBoolean( ); /读入布尔型数据public abstract byte readByte( ); /读入字节型数据public abstract char readChar( ); /读入字符型数据public abstract double readDouble( );public abstract float readFloat( );public abstract void readFully(byte b ); /读入全部数据存入字节数组b中public abstract void readFul
28、ly(byte b,int off, int len);public abstract int readInt( );public abstract String readLine( );public abstract long readLong( );public abstract short readShort( );public abstract int readUnsignedByte( );public abstract int readUnsignedShort( );public abstract String readUTF( )public abstract int skip
29、Bytes(int n); /将读取位置跳过n个字节 ,定义接口时的注意事项 (1)接口定义用关键字interface而不是class; (2)修饰符号public用来指明任意一个类都可以调用此接口;若无此修饰符,则只有那些与本接口在同一个包中的类才能访问它; (3)接口体中的数据成员全是用final static修饰的,即它们一定是给出标识符的常量,即使在定义时未写也是如此; (4)接口体中定义的方法都是抽象方法; (5)接口没有构造方法; (6)接口也具有继承性,且一个接口可以继承多个父接口。(这点与类的继承不同!),实现接口应注意问题(1)用implement声明该类将要实现哪些接口;
30、(2)若实现某接口不是abstract类,则在类定义部分必须实现指定接口的所有抽象方法。 (3)若实现某接口是abstract类,则它可以不实现该接口的方法。 (4)一个类在实现某接口的抽象方法时,必须使用完全相同的方法头。 (5)接口的抽象方法的访问限制符都已指定为public,所以类在实现方法时,必须显示使用public修饰符,否则将被系统警告为缩小了接口中定义的方法的访问控制范围。,几个直接接口中包含有同名的有名常量或相同签名(定义)的方法,将引发接口的名字冲突,一般系统将按以下方式处理: (1)父接口中有同名的有名常量,应使用指定具体有名常量的格式:. ; (2)若两个直接父接口中包含
31、有相同签名但返回类型不同方法,那么将引发编译错误; (3)若两个直接父接口中包含有相同签名且返回类型相同的方法,那么类中只能继承保留一个。,用户定义类的完整格式,修饰符 class 类名 extends父类名 implements 接口名列表 修饰符 数据成员; /声明及初始化修饰符 方法成员; /声明及方法体 ,4.3.2【综合案例4-6】,类继承并实现接口,显示接口中信息。,interface A /接口A的设计String a=“接口A中的常量“;void showA();abstract void setAColor(); interface B extends A /接口B的设计,继
32、承于AString b=“接口B中的常量“;void showB();abstract void setBColor(); interface C extends B /接口C的设计,继承于BString c=“接口C中的常量“;void showC();abstract void setCColor(); ,class ImpInterfaceABC implements C /类设计并实现接口Cpublic void showA() System.out.println(a); public void setAColor() System.out.println(“设置的是接口A的颜色!“
33、); public void showB() System.out.println(b); public void setAColor() System.out.println(“设置的是接口A的颜色!“); public void showC() System.out.println(c); public void setAColor() System.out.println(“设置的是接口A的颜色!“); public class InterfaceInheritanceTest /测试类设计public static void main(String args) ImpInterface
34、ABC intf=new ImpInterfaceABC();intf.showA(); intf.setAColor();intf.showB(); intf.setBColor();intf.showC(); intf.setCColor(); ,程序运行结果:接口A中的常量设置的是接口A的颜色!接口B中的常量设置的是接口B的颜色!接口C中的常量设置的是接口C的颜色!,课后思考:如果程序改写为体现交通工具类时,请改写程序并把不同颜色的四轮汽车和两轮自行车的颜色和类别信息显示出来。,设计类的过程中,应该注意如下事项(1)类的定义与实现是放在一起保存的,整个类必须 保存在一个文件中; (2)公
35、共类名即是文件名; (3)新类必须在已有类的基础上构造; (4)在已有类的基础上构造新类的过程称为派生; (5)派生出的新类称为已有类的子类; (6)子类继承父类的方法和属性; (7)当没有显式制定父类时,父类隐含为Java.lang包中的Object类。Object类是Java中惟一没有父类的类,是所有类的父类。 (8)extends可以继承父类的属性成员和方法成员,形成子类,也就是说子类是父类派生出来的。,抽象类和接口 区分,抽象类中可以定义成员变量和成员方法,其中可含有非抽象的成员方法。而接口中只能定义常量和没有实现的方法,方法完全是抽象的,只有声明,没有方法的具体实现。 一个子类只能继
36、承一个抽象类,但一个子类可以实现多个接口。,4.3.3 包的使用,概念(为什么使用包) 包的功能:把一个源代码文件内所定义的几个类放入到语句后面的程序包名所指定的包中。即: 1 划分类名空间;2 控制类之间的访问。,创建包,无名包系统自动为每个.java源文件创建一个无名包。该.java文件中定义的所有类隶属于这个包,它们之间(除private, protect)可以相互引用。注意:无名包的类不能被其他包中的类所利用和复用。,无名包:缺省情况 有名包:定义情况,例:package CardSystem;在当前文件夹下建立子文件夹CardSystempackage CardSystem .Car
37、dclasses;在当前文件夹下子文件夹CardSystem下建立子 文件夹Cardclasses,创建有名包 (在整个源文件的第一行)声明语句格式:package 程序包名;,程序段举例:packgae CardClasses; /创建包abstract class PCardabstract class NPCard extends Pcardclass D200 extends NPCard上述三个类的.java及.class文件都放在包名所指定的文件夹CardClasses内。,包的引用,使用包名、类名前缀在要使用的属性或方法名前加上类名作为前缀(同类)。在要使用的其它包中的类需在类名
38、前再加上包名作为前缀。例:CardClasses.D200 my200=new CardClasses.D200(12345,12);System.out.println(my200.toString( ),加载需要使用的类使用import语句将需要使用的整个类加载到当前程序 中例:import CardClasses.D200;/在程序开始加载其它包的类D200 my200=new D200(12345, 12),加载整个包使用import语句加载其它包中的一个类或引入整个包。 例: import CardClasses.*;import java.awt.*;,import 程序包名.类名
39、; import 程序包名.*;,包是可以有任意多层子包。包和子包 的名字之间用点号隔开。,包的引用_小结,1 在引入的类前加包名; 2 用import关键字加载需要使用的类包; 3 设置包的路径 :(1)先定义存放源程序的文件夹;即在源程序文件下建立一个与包名相同的子夹。(2)添加环境变量classpath的路径。将环境变量添加所引用的路径,例如:C:Program FilesEditPlus 2info; C:j2sdk1.4.0lib,有关包加载的补充说明,包:若干个扩展名为class的文件集合在一起就形成了包。 Java主包:Java 的一层包,名为java; Java主子包:Java
40、的二层包,名为lang; Java标准的扩展包:名为javax,最多只有三层。包是可以有任意多层子包。包和子包的名字之间用点号隔开。例:javax. swing.tree,常用java包汇总,包 接口和类的用途 包 接口和类的用途 java.applet applet java.rmi 远程方法调用 java.awt 图形和图形用户接口 java.rmi.dgc 支持java.rmi java.awt.datatranster 剪切和粘贴功能 java.rmi.registry 同上 java.awt.event 事件处理 java.rmi.server 同上 java.awt.image 图
41、像处理 java.security 安全 java.awt.peer 平台无关图形 java.security.acl 支持java.security java.beans 软件组件 java.security.interfaces 同上 java.io 输入输出 java.sql 数据库 java.lang 语言的核心功能 java.text 国际化 java.lang.reflect 映射(“自省”) java.util 各种工具 java.math 任意精度算术运算 java.util.zip 压缩和解压缩,常用javax子包汇总,包 包中接口和类的用途 javax.accessibil
42、ity 判定技术 javax.swing “轻便”的图形和图形用户 javax.swing.border 专用边界 javax.swing.colorchooser 颜色选择 javax.swing.event 扩展java.awt.event的事件处理 javax.swing.filechooser 文件选择 javax.swing.plaf 可插入的外观和效果 javax.swing.plaf.basic 基本的外观和效果 javax.swing.plaf.metal 金属的外观和效果 javax.swing.plaf.multi 复合体的外观和效果 javax.swing.table 数
43、据的表单表示 javax.swing.text 文本的表示和处理 javax.swing.text.html HTML文本 javax.swing.text.rtf RTF(Rich Text Format)文本 javax.swing.tree 数据的树型表示 javax.swing.undo 文本编辑中的撤消功能,常用类的学习,Object,Java类的根类; Math,数学方法类; System,系统类; 基本类型包装类。,Object类,Object类是Java中类层次树的根,所有其他类都是 从Object类直接或间接派生出来的。当一个类在定义中没有明确指定直接超类(父类) 时,编译器
44、将默认Object为其直接超类。protected Object clone( ) /生成当前对象的一个拷贝,并返回这个复制对象 public boolean equals (Object obj) /比较两个对象是否相同,是则返回true public final Class getClass( ) /获取当前对象所属的类信息,返回Class对象 protected void finalize( ) /定义回收当前对象时所需完成的清理工作 public String toString( ) /返回当前对象本身的有关信息,按字符串对象返回,Math类,Math类包含一组使用的类方法,可用语完成
45、一些常见的数学运算。 * 该类是一个final类,所以无法定义其子类; * 该类将默认的不带参数的构造方法定义成私有 (private)的,使用者无法创建这个类的实例。* 常用Math数学类:max(x)_求x最大值 min_求x最小值 pow(a,b)_ab log(x)_计算的自然对数exp(x)_ex sqrt(x)_计算x的平方根 abs(x)_|x| random( )_产生随机数,(它存在于API基本类的java.lang包中),System类,与Math类一样,System类不能派生子类,也不能实例化。常用System系统类:setIn_重新设置标准输入流;setOut_重新设置
46、标准输出流;setErr_重新设置标准错误输出流;currentTimeMiillis_获取以毫秒为单位的时间;arraycopy_数组元素的复制;getProperty_获取由key指定的系统属性值;setProperty_设置由key指定的系统属性值。,用System类获取标准输入/输出。System类的三属性:public static PrintStream err; /标准错误输出。public static InputStream in; /标准输入。例如:char c=System.in.read( );public static PrintStream out; /标准输出。例
47、如:System.out.println(“Hello! Guys.”); 用System类的方法获取系统信息,完成系统操作public static long currentTimeMillis( ); /获取两个事件发生的先后时间差public static void exit(int status); /强制虚拟机退出运行状态,并返回status信息public static void gc( ); /强制虚拟机的垃圾回收功能,基本类型包装类,数据类型类 基本数据类型Boolean booleanCharacter charDouble doubleFloat floatInteger intLong long,