Java面向对象高级特性.ppt
第五章第五章JavaJava面向对象高级特性面向对象高级特性1/28/20231/28/20231 1本章要点本章要点Static、final关键字关键字抽象类抽象类接口接口包包内部类内部类访问控制访问控制其它其它1/28/20231/28/20232 25.1 static关键字 用static(静态的)修饰的变量或方法又称为类变量和类方法。类变量(静态变量)在成员变量声明时使用static关键字。注意点:类变量只在系统加载其所在类时分配空间并 初始化,实例化对象时不再分配空间,所有 实例对象将共享类的静态变量。用途 可以用来在实例对象之间进行通信1/28/20231/28/20233 3 类似于其他语言中的全局变量,可以用类 名直接调用。如:Count.counter 例题5-1 static成员变量举例(P115)类方法(静态方法)在类的成员方法声明中带有static关键字,访问时可通过类名访问例题5-2 static方法举例(P117)类名类名StaticStatic变量变量1/28/20231/28/20234 4注意点 静态方法只能访问方法体内定义的局部变量、自己的参数和静态变量。(因静态方法不是通过调用对象实例,故在静态方法中没有this指针)子类不能重写父类的静态方法,不能将非静态方法重写为静态的方法。main()是一个静态方法,是程序的入口点可以使JVM不创建实例对象就可以运行方法。1/28/20231/28/20235 5静态初始化程序静态初始化程序 类中不属于任何方法体中,并以类中不属于任何方法体中,并以staticstatic关键字修饰的关键字修饰的语句块。语句块。如:如:static static I=5;I=5;System.out.println(“Static System.out.println(“Static code:I=”+I+);code:I=”+I+);注意注意 静态语句块只在加载类时执行一次,通常用来静态语句块只在加载类时执行一次,通常用来 进行类成员变量的初始化。进行类成员变量的初始化。例题例题5-35-3:静态语句块与静态变量的访问。:静态语句块与静态变量的访问。1/28/20231/28/20236 65.2 final关键字在Java中,可以用final关键字声明类、成员 方法、成员变量。被定义成final的类不能再派生子类如:Java.lang.String为一个final类。被定义为final的方法不能重写,优点是在运行时进行效率优化。被定义为final的变量只能被赋值一次,常 用来定义常量,变量名一般大写。例题5-4 final 变量在构造方法中赋值1/28/20231/28/20237 75.3抽象类抽象方法抽象方法 只有定义而没有方法体的方法。只有定义而没有方法体的方法。抽象类抽象类 包含一个或多个抽象方法的类。包含一个或多个抽象方法的类。定义抽象类的格式为:定义抽象类的格式为:abstract class abstract class 抽象类名抽象类名 注意点注意点 抽象类不能实例化。可派生子类,在子类中 具体定义方法的功能。1/28/20231/28/20238 8 目的是为一类对象建立抽象的模型,在同类对象所对应的体系中抽象类往往位距顶层。使类的设计变的清晰、支持多态、为类的体 系提供通用的接口。1/28/20231/28/20239 9 Employee e=new Manager();/Employee e=new Manager();/正确正确 Employee e=new Employee();/Employee e=new Employee();/错误错误abstract class Employee abstract void raiseSallory(int i);Class Manager extends Employee void raiseSallory(int i);1/28/20231/28/202310105.4 接口接口定义格式接口定义格式:修饰符修饰符interfaceinterface接口名接口名extends extends 父接父接 接口体接口体;修饰符为修饰符为publicpublic时,指明任何类均可以使时,指明任何类均可以使用这个接口。用这个接口。修饰符缺省时,只有与该接口定义在同一修饰符缺省时,只有与该接口定义在同一个包中的类才可以访问该接口个包中的类才可以访问该接口1/28/20231/28/20231111接口的实现与使用 implements 关键字用来表示实现某个接口,在类体中可以使用接口中定义的常量,且须实现接口中定义的所有方法。一个类可以实现多个接口,在implements中用“,”分隔。例如:Public interface Flyer public void takeoff();public void land();public void fly();1/28/20231/28/20231212Public class Airplane implements Flyer public void takeoff()/实现起飞的操作实现起飞的操作 public void land()/下落下落 public void fly()/起飞起飞 例题例题5-5:通过接口实现多态示例:通过接口实现多态示例.1/28/20231/28/20231313多重继承Java中规定一个类只能继承一个父类,但可以实现多个接口,Java是利用接口实现多重继承的。父类方法父类方法 interface_1 interface2 interface_n抽象或具体父类抽象或具体父类Interface_1Interface_2Interface_n子类子类1/28/20231/28/20231414通过继承扩展接口通过创建接口的子接口来增加新的方法。通过创建接口的子接口来增加新的方法。如:如:Interface Shape void draw();void erase();interface ShapeArea extends Shape double area();1/28/20231/28/20231515接口与抽象类 两者有一定的相似,又有区别接口中方法都是抽象的,而抽象类中可以定义带有方法体的不同方法一个类可以实现多个接口,而只可继承一个抽象父类接口不是类体系的一部分,即与实现它的类不构成继承体系。抽象类通常位于类体系顶层。接口可用于多重继承。1/28/20231/28/202316165.5 包包的概念包的概念 Java Java中包是相关类与接口的一个集合,它提供了命名中包是相关类与接口的一个集合,它提供了命名空间的管理和访问。包具有特定的访问控制权限。空间的管理和访问。包具有特定的访问控制权限。Java Java中编译器把包对应于文件系统的目录和文件管理,中编译器把包对应于文件系统的目录和文件管理,还可以使用压宿文件的格式存储。还可以使用压宿文件的格式存储。JDK JDK中提供的包有中提供的包有 Java.applet Java.awt Java.event Java.applet Java.awt Java.event等。等。例如:名为例如:名为 Java.applet Java.applet的包中,所有类文件都存储的包中,所有类文件都存储在目录在目录 classpathjavaapplet classpathjavaapplet 下,这里下,这里classpathclasspath由由环境变量来设定。环境变量来设定。1/28/20231/28/20231717包机制的优点易根据包中类的功能找到所需要的类,包中的类是易根据包中类的功能找到所需要的类,包中的类是相关的。相关的。每个包都是命名空间,不同包中类的名字不冲突。每个包都是命名空间,不同包中类的名字不冲突。同一个包中的类之间有比较宽松的访问机制。同一个包中的类之间有比较宽松的访问机制。包的定义与使用 定义用关键字定义用关键字 package package 如:如:package graphics;package graphics;说明:说明:.packagepackage语句指定某类加入语句指定某类加入graphicsgraphics包,并存放路径包,并存放路径 为为 classpathgraphics classpathgraphics1/28/20231/28/20231818.如原文件中没有package语句,则指定为无名包,通常放在源文件的目录下。.package只能有一条,并在源程序的第一行。.一个类只能属于一个包.包名以“.”为分隔符 1/28/20231/28/20231919使用包成员import import 语句放在源程序的前面语句放在源程序的前面 如:如:import graphics.circle/import graphics.circle/引入包中的引入包中的CircleCircle类类 import graphics.*/import graphics.*/引入包中所有的类引入包中所有的类 如果没有用如果没有用importimport语句引入包的类,则可用长名语句引入包的类,则可用长名 引用类引用类 格式:格式:包名包名.类名类名 如:如:graphics.circle mycircle=new graphics.circle()graphics.circle mycircle=new graphics.circle()通常没有必要这样做。通常没有必要这样做。1/28/20231/28/20232020包使用示例例5.6定义二维几何图形的包并使用 1/28/20231/28/202321215.6访问控制Java中有四中不同的访问权限 private-私有的 protected-受保护的 public-公开的 缺省(default)权限权限修饰符修饰符 同一类同一类 同一包同一包 子类子类 全局全局 private private Y Y default default Y Y Y Yprotectedprotected Y Y Y Y Y Ypublicpublic Y Y Y Y Y Y Y Y1/28/20231/28/202322225.7 内部类内部类是在一个类的定义中定义的类,也称为嵌套类。内部类可作为外包类(包容类)的一个成员使用,可以访问外包类的所有成员(包括带有static、private的成员变量和方法)。例题5-8 内部类访问外包类成员(P139)例题5-9 内部类通过修饰符访问同名外包类成员(P140)1/28/20231/28/20232323在外包类的语句块中定义内部类内部类可以定义在一个方法体的语句块中定义,这时内部类可以访问语句块中的局部变量,但只限于在该语句块运行期内,当该方法运行结束后内部类对象将不能访问所在语句块中的局部变量。例题5-101/28/20231/28/20232424在外包类以外的其他类中访问内部类对于可在外包类之外访问的内部类,引用内部类时必须使用完整的标识:外包名.内部类名 假设B 是A的内部类则有 A a=new A()A.B b=a.new B()例题5-11 在外包类之外访问内部类1/28/20231/28/20232525内部类的特点内部类的特点:内部类可以使用它所在类的静态成员变量、内部类可以使用它所在类的静态成员变量、实例成员变量和方法中的局部变量。实例成员变量和方法中的局部变量。内部类的修饰符有内部类的修饰符有abstractabstract,privateprivate或或protectedprotected。内部类可作为其他类的成员。内部类可作为其他类的成员。1/28/20231/28/202326265.8 其它 基本数据类型的包装类 集合类 1/28/20231/28/202327275.8.1 基本数据包装类 基本数据类型在基本数据类型在java.langjava.lang包中都有一个包中都有一个wrapperwrapper类。类。基本数据类型基本数据类型WrapperWrapper类类基本数据类型基本数据类型WrapperWrapper类类 boolean boolean Boolean BooleancharcharCharacterCharacter byte byte Byte BytelonglongLongLong short shortShortShortfloatfloatFloatFloat int intIntegerIntegerdoubledoubleDoubleDouble1/28/20231/28/20232828每个包装类中提供了有用的方法和常量MIN_VALUE MAX_VALUE数据类型的转换 Integer wint=new Integer(18);Integer wint=new Integer(18);int p=wint.intValue();int p=wint.intValue();int x=Integer.valueof(“123”).intValue();int x=Integer.valueof(“123”).intValue();int y=Integer.parseInt(“123”);int y=Integer.parseInt(“123”);String s=(new Integer(125).toString();String s=(new Integer(125).toString();1/28/20231/28/202329298.2集合类集合包含一组对象。在这个对象中存放指向其他对象的引用Java Collection API的核心接口的核心接口 colletion List SetSortedSet Map SortedMap1/28/20231/28/20233030CollectionCollection CollectionCollection接口是集合接口的根,它定义了集合的接口是集合接口的根,它定义了集合的通用通用APIAPI。JDKJDK中没有提供该接口的实现类,而是中没有提供该接口的实现类,而是提供了它的子接口。例如:提供了它的子接口。例如:SETSET和和LISTLISTSet set set中的元素不能重复,是数学中集合的抽象中的元素不能重复,是数学中集合的抽象List List List是一个有序的集合,称为列表或序列。可以包是一个有序的集合,称为列表或序列。可以包含重复的元素,矢量含重复的元素,矢量VectorVector就是一种常用的就是一种常用的ListList。1/28/20231/28/20233131Map Map Map实现键值到值的映射。实现键值到值的映射。MapMap中不能包含重复中不能包含重复的键值,每个键值最多只能映射到一个值。的键值,每个键值最多只能映射到一个值。HashtableHashtable就是一个常用的就是一个常用的MapMap。SortedSet 和SortedMap SortedSet SortedSet 和和SortedMapSortedMap分别是具有排序性能的分别是具有排序性能的SetSet和和MapMap。1/28/20231/28/20233232几种常用的集合Set Set Set继承了接口继承了接口CollectionCollection接口,包含的方法都是接口,包含的方法都是从从CollectionCollection接口继承而来。包含方法见接口继承而来。包含方法见P145P145 在在JDKJDK中实现了中实现了SetSet接口的实用类有:接口的实用类有:HashSetHashSet类类TreeSetTreeSet类类LinkedHashsetLinkedHashset类。类。HashSet HashSet类是采用类是采用HashHash表实现了表实现了SetSet接口。其中元素接口。其中元素存储在一个存储在一个HashHash表中,并且这些元素没有固定的表中,并且这些元素没有固定的顺序。由于采用顺序。由于采用HashHash表,当集合中元素数量较大表,当集合中元素数量较大时其访问效率比线性表要快。时其访问效率比线性表要快。1/28/20231/28/20233333实现Set的示例例题5-12 SetSet的示例的示例import java.util.*;public class FindDups public static void main(String args)Set s=new HashSet();/创建一个HashSet对象,缺省的初始容量是16。for(int i=0;iargs.length;i+)/将命令行中的每个字符串加入到集合s中,其中重复的字符串将不能加入,并被打印输出。if(!s.add(argsi)System.out.println(Duplicate detected:+argsi);System.out.println(s.size()+distinct words detected:+s);/输出集合s的元素个数以及集合中的所有元素。1/28/20231/28/20233434TreeSet TreeSet TreeSet 类实现了类实现了SortedSetSortedSet接口接口,采用树型结构存采用树型结构存储集合中的元素,储集合中的元素,TreeSet TreeSet对象中元素按照升序排对象中元素按照升序排序。序。LinkedHashSetLinkedHashSetLinkedHashSetLinkedHashSet类实现了类实现了SetSet接口,采用接口,采用HashHash表和链表和链表相结合的结构存储元素。它结合了表相结合的结构存储元素。它结合了HashSetHashSet和和 TreeSetTreeSet的优点,既能保证集合中元素的顺序又能的优点,既能保证集合中元素的顺序又能保证有较高的存取效率。保证有较高的存取效率。1/28/20231/28/20233535List ListList是一种有序的集合,它继承了是一种有序的集合,它继承了CollectionCollection接口接口同时又增加了操作同时又增加了操作按位置存取元素按位置存取元素查找查找遍历遍历子子ListList的截取的截取 List List接口的定义接口的定义P147P1471/28/20231/28/20233636JDK中提供了实现List接口的三个类:ArrayList类、LinkList类和Vector类。ArrayList类 ArrayListArrayList类采用可变大小的数组实现类采用可变大小的数组实现ListList接口。接口。增加了访问数组大小的方法。增加了访问数组大小的方法。ArrayListArrayList对象会随着元对象会随着元素的增加而容积自动扩大。素的增加而容积自动扩大。ArrayList ArrayList是三种类中效率是三种类中效率最高的也是最常用的。最高的也是最常用的。例题:例题:5-13 List5-13 List使用的示例使用的示例1/28/20231/28/20233737LinkList类 LinkList LinkList类采用链表结构实现类采用链表结构实现ListList接口。除了实现接口。除了实现ListList接口中的方法外还提供了在链表的头和尾进行接口中的方法外还提供了在链表的头和尾进行getget、removeremove和和insertinsert等操作。利用这些操作可以等操作。利用这些操作可以用来实现象数据结构中的堆栈、队列等数据结构。用来实现象数据结构中的堆栈、队列等数据结构。Vector类 采用可变体积的数组实现采用可变体积的数组实现ListList接口。该类同数组一接口。该类同数组一样可以通过索引序号对所包含的元素进行访问。样可以通过索引序号对所包含的元素进行访问。1/28/20231/28/20233838Map Map包含了一系列键值和值之间的映射关系。一个Map对象可以看成是 一个键值和值对的集合,可以在该集合中通过一个键找到对应的值。键和值可以是任意的对象。Map接口独立于Collection接口体系的,Map接口的定义如P149。1/28/20231/28/20233939实现的5个Map接口的实用类 HashMap HashMap类、类、HashTableHashTable类类、TreeMapTreeMap类类、WeekHashMapWeekHashMap类、类、IdentityHashMapIdentityHashMap类类HashMapHashMap类和类和HashTableHashTable类类 都使用都使用HashHash表实现表实现MapMap接口,两者基本等价。接口,两者基本等价。TreeMapTreeMap类类 采用有序树的结构实现采用有序树的结构实现MapMap接口,同接口,同TreeMapTreeMap相类似。相类似。该类按照键的升序的次序排列元素。该类按照键的升序的次序排列元素。WeekHashMapWeekHashMap类类 与与HashMapHashMap类相类似,但类相类似,但WeekHashMapWeekHashMap类中的键类中的键值在不被使用时会自动删除,由垃圾收集器回值在不被使用时会自动删除,由垃圾收集器回收。收。1/28/20231/28/20234040IdentityHashMapIdentityHashMap类类 其特殊之处是在比较两个键值是否相同是,比较其特殊之处是在比较两个键值是否相同是,比较的是键的引用,而不是键对象自身。的是键的引用,而不是键对象自身。上述上述MapMap类中,类中,HashMapHashMap(无序的(无序的MapMap)TreeMap TreeMap(有序的(有序的MapMap)例题例题5-145-14:利用:利用MapMap进行单词词频的统计。进行单词词频的统计。1/28/20231/28/20234141集合元素的遍历Java CollectionsAPI为集合提供了Iterator(重复器)用来遍历集合中的元素。其中的方法可以使我们向前遍历所有类型的集合。对一个Set对象的遍历次序是不确定的。对List对象的遍历次序是从前向后。而其子接口ListIterator支持从后向前的反向遍历。1/28/20231/28/20234242Iterator接口包含两个接口Iterator 和ListIterator public interface Iterator public interface Iterator boolean hasNext();boolean hasNext();Object next();Object next();Void remove();/Void remove();/删除当前遍历到的元素,即删除最近删除当前遍历到的元素,即删除最近一次一次next()next()或或PreviousPrevious()调用返回的元素。()调用返回的元素。1/28/20231/28/20234343ListIterator public interface ListIterator extends Iterator public interface ListIterator extends Iterator boolean hasNext();boolean hasNext();Object next();Object next();boolean hasPrevious();boolean hasPrevious();object previous();object previous();int nextIndex();int nextIndex();int previousIndex();int previousIndex();remove();remove();void set(object o);/void set(object o);/可以改变当前遍历到的元素可以改变当前遍历到的元素 void add(object o);/void add(object o);/在下一个将要取得的元素之前插入新的在下一个将要取得的元素之前插入新的元素。元素。1/28/20231/28/20234444例题5-15:ListIteratorListIterator的使用示例的使用示例1/28/20231/28/20234545枚举、自动装箱和静态导入枚举 枚举枚举enumerationenumeration是许多编程语言都有的,但是许多编程语言都有的,但早期的版本并没有提供枚举。其原因就是枚举不早期的版本并没有提供枚举。其原因就是枚举不是必需的。是必需的。但是在日常生活中非常常见,在但是在日常生活中非常常见,在J2SE5(2004J2SE5(2004年发年发布布)添加了枚举类型。添加了枚举类型。1/28/20231/28/20234646enum Transportenum Transport CAR,TRUCK,AIRPLANE,TRAIN,BOAT CAR,TRUCK,AIRPLANE,TRAIN,BOAT Transport tp;Transport tp;tp=Transport.AIRPLANE;tp=Transport.AIRPLANE;可以使用的场合可以使用的场合 if(tp=Transport.TRAIN)if(tp=Transport.TRAIN)switch(tp)switch(tp)case CAR:case CAR:case TRUCK:case TRUCK:注意:在注意:在casecase中,枚举常量没有使用枚举类型名来限定。中,枚举常量没有使用枚举类型名来限定。1/28/20231/28/20234747例题:enum Transportenum Transport CAR,TRUCK,AIRPLANE,TRAIN,BOAT CAR,TRUCK,AIRPLANE,TRAIN,BOATclass EnumDemoclass EnumDemo public static void main(String args)public static void main(String args)Transport tp;Transport tp;tp=Transport.AIRPLANE;tp=Transport.AIRPLANE;System.out.println(“value of tp”+tp);System.out.println(“value of tp”+tp);tp=Transport.TRAIN;tp=Transport.TRAIN;if(tp=Transport.TRAIN)if(tp=Transport.TRAIN)System.out.println(“tp contains Train.”);System.out.println(“tp contains Train.”);1/28/20231/28/20234848switch(tp)switch(tp)case CAR case CAR System.out.println(“A car carries people.”);break;System.out.println(“A car carries people.”);break;case TRUCK:case TRUCK:System.out.println(“A truck carries freight.”);break;System.out.println(“A truck carries freight.”);break;case AIRPLANE:case AIRPLANE:System.out.println(“A airplane flies.”);break;System.out.println(“A airplane flies.”);break;case TRAIN:case TRAIN:System.out.println(“A train runs on rails.”);break;System.out.println(“A train runs on rails.”);break;case BOAT:case BOAT:System.out.println(“A boat sails on water.”);break;System.out.println(“A boat sails on water.”);break;Value of tp:AIRPLANEAIRPLANETp contains Tp contains TRAIN.TRAIN.A tarin runs on rails.A tarin runs on rails.1/28/20231/28/20234949Java的枚举类型是类类型从前面的例题可见,枚举类型为类类型。但不使用new实例化enum。如:Transport tp;Transport tp;tp=Transport.AIRPLANE;tp=Transport.AIRPLANE;例题例题5-16 5-16:1/28/20231/28/20235050values()和valueof()方法 所有的枚举类型自动地拥有方法:values()values()valueof()valueof()方法。其形式如下:方法。其形式如下:public static enum-type values()public static enum-type values()返回一个包含枚举常量列表的数组返回一个包含枚举常量列表的数组 public static enum-type valueof(String str)public static enum-type valueof(String str)返回一个枚举常量,其值对应于传递给返回一个枚举常量,其值对应于传递给StrStr的字符的字符串。串。例题例题5-175-17:1/28/20231/28/20235151构造方法、方法、实例变量和枚举每个枚举常量是一个枚举型的对象;枚举类型可以定义构造函数,添加方法。例题5-18:1/28/20231/28/20235252自动装箱和自动拆箱包装类包装类 Integer iob=new Integer(100);Integer iob=new Integer(100);int i=iob.intValue();int i=iob.intValue();称为手工装箱、手工拆箱称为手工装箱、手工拆箱 Integer iob=10);Integer iob=10);int i=iob;int i=iob;称为自动装箱、自动拆箱称为自动装箱、自动拆箱1/28/20231/28/20235353静态导入 import static java.lang.Math.sqrt;import static java.lang.Math.pow;x=sqrt(144);y=pow(b,2);import static java.lang.Math.*;注意:不能滥用,会导致命名冲突。1/28/20231/28/20235454泛型参数化类型参数化类型一个简单的范型示例一个简单的范型示例 5-20 5-20泛型代码的优点是可以自动地处理传递给其类型参泛型代码的优点是可以自动地处理传递给其类型参数的数据类型,不管应用了什么数据类型,许多算数的数据类型,不管应用了什么数据类型,许多算法在逻辑上都是相同的。例如:快速排序算法不管法在逻辑上都是相同的。例如:快速排序算法不管其排序项目是整型、字符型、其排序项目是整型、字符型、OBJECTOBJECT或或THREADTHREAD其其逻辑都是相同的。逻辑都是相同的。泛型的语法格式泛型的语法格式class class-name/class class-name/定义定义class-name=class-name=new class-name(cons-arg-list)new class-name(cons-arg-list)1/28/20231/28/20235555范型只能用于对象 Genintob=new Gen(53);/错误范型类不同于普通类的对象 iob=strob /Wrong!可以带有多个参数 例题5-21:带有两个类型参数的范型类约束类型 例如:1/28/20231/28/20235656泛型方法 boolean arrayEqual(boolean arrayEqual(T x,V y)T x,V y)if(x.length!=y.length)return false;if(x.length!=y.length)return false;for(int i=0;ix.length;i+)for(int i=0;ix.length;i+)if(xi!=yi)return false;if(xi!=yi)return false;return true;return true;1/28/20231/28/20235757范型接口Interface ContainmentInterface Containment boolean contains(T o);boolean contains(T o);/实现范型接口的类自身必须是范型的实现范型接口的类自身必须是范型的Class MyClassimplements ContainmentClass MyClassimplements Containment T arrayRef;T arrayRef;MyClass(T o)arrayRef=o;MyClass(T o)arrayRef=o;boolean contains(T o);boolean contains(T o);1/28/20231/28/20235858