Java语言程序设计 课件 第9章 接口与内部类_第1页
Java语言程序设计 课件 第9章 接口与内部类_第2页
Java语言程序设计 课件 第9章 接口与内部类_第3页
Java语言程序设计 课件 第9章 接口与内部类_第4页
Java语言程序设计 课件 第9章 接口与内部类_第5页
已阅读5页,还剩61页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java语言程序设计第9章接口与内部类

1接口23主要内容Java语言程序设计(第4版)清华大学出版社2022接口的非抽象方法内部类45接口示例案例:比较员工对象大小Java语言程序设计9.1接口接口(interface)定义了一种可以被类层次中的任何类实现的行为的契约,是常量、抽象方法、默认方法、静态方法和私有方法的集合。接口可以用来实现多重继承。9.1.1接口定义接口的定义与类的定义类似,包括接口声明和接口体两部分。接口声明使用interface关键字,格式如下:[public]interfaceInterfaceName[extendsSuperInterfaces]{//接口体定义}InterfaceName为接口名。extends表示该接口继承(扩展)了哪些接口。如果接口使用public修饰,则该接口可以被所有的类使用,否则接口只能被同一个包中的类使用。9.1.1接口定义大括号内为接口体,接口体中可以定义常量、抽象方法、默认方法、静态方法和私有方法等。下面代码定义了一个简单接口Eatable(可吃的)。publicinterfaceEatable{publicintSTATUS=100;publicabstractStringhowToEat();

//抽象方法的定义}9.1.1接口定义接口中的抽象方法只有声明,没有实现。抽象方法也可以省略修饰符,省略修饰符编译器自动加上public、abstract,下面两行代码等价。publicabstractStringhowToEat();StringhowToEat();接口被看做是一种特殊的类型。与常规类一样,每个接口都被编译为独立的字节码文件。使用接口有点像使用抽象类。接口可以作为引用变量的数据类型或类型转换的结果等。与抽象类一样,不能用new运算符创建接口的实例。9.1.1接口定义在UML中,接口的表示与类图类似,图9-1是Eatable接口的UML图,其中接口名上方使用<<interface>>表示接口,接口名和抽象方法名使用斜体表示。定义在接口中的任何变量都自动加上public、final、static属性,因此它们都是常量,常量的定义可以省略修饰符,下面三行代码效果相同。intSTATUS=100;publicintSTATUS=100;publicfinalstaticintSTATUS=100;9.1.2常量按照Java标识符命名惯例,常量名都使用大写字母命名。接口中的常量应该使用接口名引用。不推荐在接口中定义常量,因为使用枚举类型描述一组常量集合比接口中定义常量更好。实现接口就是实现接口中定义的抽象方法,这需要在类声明中用implements子句来表示实现接口,一般格式如下:[public]classClassNameimplementsInterfaceList{//类体定义}9.1.3接口的实现一个类可以实现多个接口,这需要在implements子句中指定要实现的接口并用逗号分隔。在这种情况下如果把接口理解成特殊的类,那么这个类利用接口实际上实现了多继承。一个类在实现某接口的抽象方法时,必须使用与接口完全相同的方法签名,否则只是重载的方法而不是实现已有的抽象方法。接口方法的访问修饰符都是public,所以类在实现方法时,必须显式使用public修饰符,否则编译器警告缩小了访问控制范围。下面的Mutton类实现了Eatable接口。9.1.3接口的实现packagecom.boda.xy;publicclassMuttonimplementsEatable{@OverridepublicStringhowToEat(){return"烤羊肉串";

}}程序9.2Mutton.java一个接口可以继承一个或多个接口。下面代码定义了三个接口,其中CC接口继承了AA接口和BB接口。9.1.4接口的继承packagecom.boda.xy;publicinterfaceAA{intSTATUS=100;//常量声明publicabstractvoiddisplay();//一个抽象方法}程序9.3AA.javapackagecom.boda.xy;publicinterfaceBB{publicabstractvoidshow();//一个抽象方法publicdefaultvoidprint(){//一个默认方法System.out.println("这是接口BB的默认方法");}}程序9.4BB.javapackagecom.boda.xy;publicinterfaceCCextendsAA,BB{intNUM=3;//定义一个常量}程序9.5CC.java接口可以多继承与类的继承类似,子接口继承父接口中的常量、抽象方法、默认方法。在接口CC中,除本身定义的常量和各种方法外,它将继承所有超接口中的常量和方法,因此,在接口CC中包含2个常量、2个抽象方法和一个默认方法。与类的继承不同的是,接口可以多继承。9.1.4接口的继承一个类要实现CC接口,它必须实现CC接口的两个抽象方法,请看下面代码。publicclassDDimplementsCC{//实现AA接口中的display方法publicvoiddisplay(){System.out.println("接口AA的display方法");}//实现BB接口中的show方法publicvoidshow(){System.out.println("接口BB的show方法");}}程序9.6DD.java//测试DD类的使用publicstaticvoidmain(String[]args){DDdd=newDD();System.out.println(DD.STATUS);dd.show();dd.print();//调用继承来的默认方法AAaa=newDD();aa.display();}一个类也可以实现多个接口,下面的AB类实现了AA接口和BB接口。publicclassABimplementsAA,BB{@Overridepublicvoiddisplay(){System.out.println("AA接口的display方法");}@Override

publicvoidshow(){System.out.println("BB接口的show方法");

}}程序9.7AB.java接口也是一种引用类型,任何实现该接口的实例都可以存储在该接口类型的变量中。AAaa=newDD();//向上自动类型转换BBbb=newDD();CCcc=newDD();9.1.5接口类型的使用当通过接口对象调用某个方法时,Java运行时系统确定该调用哪个类中的方法。

aa.display();//调用实现类的方法

bb.show();cc.print();//调用继承的默认方法

6.1.1课堂讨论及训练Java语言程序设计(第4版)

QQ群:2886394861.设计一个名为Swimmable的接口,其中包含voidswim()方法,设计另一个名为Flyable的接口,其中包含voidfly()方法。2.定义一个Duck类实现上述两个接口。3.定义测试类,演示接口类型的使用。Java语言程序设计9.2接口的非抽象方法在Java的早期版本中,接口的方法只能定义为抽象的。从Java8开始可以在接口中定义静态方法和默认方法。从Java9开始在接口中还可以定义私有方法。这三种方法都是具体实现的方法。下面来学习这几种方法的定义。概述从Java8开始,可以在接口中定义静态方法,与接口有关的静态方法都可以在接口中定义,而不再需要辅助类。定义静态方法使用static关键字,默认的访问修饰符是public。9.2.1静态方法

publicinterfaceSS{intSTATUS=100;publicstaticvoiddisplay(){//静态方法System.out.println(STATUS);}}可以给接口中任何方法提供一个默认实现,这称为默认方法(defaultmethod)。默认方法需要使用default关键字定义。9.2.2默认方法publicinterfaceBB{publicdefaultvoidprint(){//一个默认方法System.out.println("这是接口BB的默认方法");}}默认方法可以被子接口和实现类继承,但子接口中若定义相同的默认方法,父接口的默认方法被隐藏。默认方法需要通过引用变量调用。从Java9开始,还可以在接口中定义私有方法。私有方法通常实现某种行为,这些行为可以被默认方法调用。9.2.3私有方法也可以定义静态私有方法,静态私有方法可以被接口的静态方法调用,也可以被默认方法调用。如果使用默认方法开发API,那么接口私有方法可能有助于实现其部分功能。publicinterfaceMyInterface{

staticprivatevoidinit2(){System.out.println("静态私有方法");}publicstaticvoidm(){init2();}

privatevoidinit(){System.out.println("完成某些初始化操作");}voidnormalInterfaceMethod();defaultvoiddefaultMethod(){init();init2();}defaultvoidanotherDefaultMethod(){init();}}Java语言程序设计9.3内部类Java语言允许在一个类(或接口)的内部定义另一个类(接口、枚举、记录或注解等,这种类称为内部类(innerclass)。使用内部类可以带来如下好处:对只在一处使用的类进行分组;提高封装性;增强代码的可读性和可维护性。有多种类型的内部类。大致可分为:成员内部类静态内部类匿名内部类局部内部类概述成员内部类是没有用static修饰且定义在外层类的类体中。下面程序在Outer类中定义了一个成员内部类Inner。9.3.1成员内部类publicclassOuter{privateintx=200;publicclassInner{inty=300;publicintcalculate(){returnx+y;}}publicvoidmakeInner(){Inneric=newInner();//创建内部类对象System.out.println(ic.calculate());}程序9.8Outer.java这是一个内部类publicstaticvoidmain(String[]args){varouter=newOuter();varinner=outer.newInner();System.out.println(inner.calculate());//输出:500}内部类编译后将单独生成一个类文件,如上述代码编译后将生成两个类文件:Outer.class和Outer$InnerClass.class。在成员内部类中可以定义自己的成员变量和方法(如calculate()),也可以定义自己的构造方法。成员内部类的访问修饰符可以是private、public、protected或缺省。9.3.1成员内部类在外层类的方法中(如makeInner)可以直接创建内部类的实例。在外层类的外面要创建内部类的实例必须先创建一个外层类的对象,因为内部类对象对外层类对象有一个隐含的引用。创建内部类对象也可以使用下面的语句实现:varinner=newOuter().newInner();在使用成员内部类时需要注意下面几个问题:成员内部类中不能定义static变量和static方法。成员内部类也可以使用abstract和final修饰,其含义与其他类一样。成员内部类还可以使用private、public、protected或包可访问修饰符。9.3.1成员内部类静态内部类使用static修饰,静态内部类也称嵌套类(nestedclass),静态内部类与成员内部类的行为不同,下面是它们的不同之处:静态内部类中可以定义静态成员,而成员内部类不能。静态内部类只能访问外层类的静态成员。成员内部类可以访问外层类的实例成员和静态成员。创建静态内部类的实例不需要先创建一个外层类的实例。相反,创建成员内部类实例,必须先创建一个外层类的实例。9.3.2静态内部类publicclassOuter2{privatestaticintx=100;publicstaticclassInner2{privateStringy="hello";publicvoidinnerMethod(){System.out.println("xis"+x);//可以访问外层类的静态成员xSystem.out.println("yis"+y);}}publicstaticvoidmain(String[]args){Outer2.Inner2snc=newOuter2.Inner2();snc.innerMethod();}}程序9.9Outer2.java在类的内部还可以定义内部接口,内部接口的隐含属性是static的,当然也可以指定。嵌套的类或接口可以有任何访问修饰符,如public、protected、private以及缺省。在内部类中还可以定义下一层的内部类,形成类的多层嵌套。内部接口publicclassOuter3{Strings1="Hello";

staticStrings2="World";

interfaceMyInterface{

abstractvoidshow();

}

staticclassInner3implementsMyInterface{

publicvoidshow(){System.out.println("s1="+newOuter3().s1);System.out.println("s2="+s2);//可以访问外层类的static变量

}

}程序9.10Outer3.java

publicstaticvoidmain(String[]args){Outer3.Inner3inner3=newOuter3.Inner3();inner3.show();

}定义类最终目的是创建一个类的实例,但如果某个类的实例只使用一次,可以将类的定义和实例的创建在一起完成,或者说在定义类的同时创建一个实例。以这种方式定义的没有名字的类称为匿名内部类(anonymousinnerclass)。9.3.3匿名内部类声明和构建匿名内部类的一般格式如下:newTypeName(){/*此处为类体*/}匿名内部类可以实现一个接口或继承一个类,这里TypeName是匿名内部类所实现的接口或继承的类。如果实现一个接口,该类是Object类的直接子类。匿名类继承一个类或实现一个接口不需要使用extends或implements关键字。匿名内部类不能同时继承一个类和实现一个接口,也不能实现多个接口。9.3.3匿名内部类由于匿名内部类没有名称,所以类体中不能定义构造方法。由于不知道类名,所以只能在定义类的同时用new关键字创建类的实例。实际上,匿名内部类的定义、创建对象发生在同一个地方。另外,上式是一个表达式,它返回一个对象的引用,所以可以直接使用或将其赋给一个引用变量。TypeNameobj=newTypeName(){/*此处为类体*/};9.3.3匿名内部类同样,也可以将构建的对象作为方法调用的参数。someMethod(newTypeName(){/*此处为类体*/});interfacePrintable{publicabstractvoidprint(Stringmessage);}publicclassPrintableTest{publicstaticvoidmain(String[]args){Printableprinter=newPrintable(){@Overridepublicvoidprint(Stringmessage){System.out.println(message);}};printer.print("这是惠普打印机");}}程序9.11PrintableTest.javaclassAnimal{publicvoideat(){System.out.println("Ilikeeatanything.");}}程序9.12AnimalTest.javapublicclassAnimalTest{publicstaticvoidmain(String[]args){Animaldog=newAnimal(){//继承Animal类@Overridepublicvoideat(){System.out.println("Ilikeeatbones.");}};//这里的分号是赋值语句的结束dog.eat();}}匿名内部类的一个重要应用是编写JavaFX图形界面的事件处理程序。如为按钮对象button注册事件处理器,就可以使用匿名内部类。9.3.3匿名内部类button.setOnAction(newEventHandler<ActionEvent>(){@Overridepublicvoidhandle(ActionEventevent){label.setText("你单击了'确定'按钮");}});可以在方法体或语句块内定义类。在方法体或语句块(包括方法、构造方法、局部块、初始化块或静态初始化块)内部定义的类称为局部内部类(localinnerclass)。9.3.4局部内部类局部内部类不能视作外部类的成员,只对局部块有效,如同局部变量一样,在说明它的块之外完全不能访问,因此也不能有任何访问修饰符。Java语言程序设计9.4接口示例Java类库中也定义了许多接口,有些接口中没有定义任何方法,这些接口称为标识接口,如java.lang包中定义的Cloneable接口、java.io包中的Serializable接口。概述有些接口中定义了若干方法,如java.lang包中的Comparable<T>接口中定义了comapreTo()方法,AutoClosable接口定义了close()方法,Runnable接口中定义了run()方法。要想比较类实例(如Circle类或Employee类)对象的大小,需要实现Comparable<T>接口。该接口的定义如下:9.4.1Comparable<T>接口packagejava.lang;publicinterfaceComparable<T>{intcompareTo(Tother);}如果希望一个类的对象能够比较大小,类必须实现Comparable<T>接口的compareTo()方法。该方法实现当前对象与参数对象比较,返回一个整数值。9.4.1Comparable<T>接口当调用对象小于、等于、大于参数对象时,该方法分别返回负整数、0和正整数。按这种方法比较出的对象顺序称为自然顺序(naturalorder)。下面程序说明了如何通过实现Comparable<T>接口对Circle类的对象根据其面积大小进行比较。publicclassCircleimplementsComparable<Circle>{privatedoubleradius;publicCircle(){}publicCircle(doubleradius){this.radius=radius;}publicdoublegetPerimeter(){//求周长方法return2*radius*Math.PI;}程序9.14Circle.javapublicdoublegetArea(){//求面积方法returnradius*radius*Math.PI;}

@Override

publicintcompareTo(Circlecircle){if(getArea()>circle.getArea())return1;elseif(getArea()<circle.getArea())return-1;elsereturn0;}publicstaticvoidmain(String[]args){Circle[]circles=newCircle[]{newCircle(3.4),newCircle(2.5),newCircle(5.8),};System.out.println(circles[0].compareTo(circles[1]));//对circles数组中3个Circle对象排序

Arrays.sort(circles);for(Circlec:circles)System.out.printf("%6.2f%n",c.getArea());}JavaAPI中许多类实现了Comparable<T>接口,如基本数据类型包装类(Byte、Short、Integer、Long、Float、Double、Character、Boolean),File类、String类、LocalDate类,BigInteger类和BigDecimal类也实现了Comparable<T>接口,这些类的对象都可按自然顺序排序。9.4.1Comparable<T>接口下面代码比较两个本地日期的大小。vard1=LocalDate.now();vard2=LocalDate.of(2022,10,1);System.out.println(pareTo(d2));//输出:1假设需要根据长度而不是字典顺序对字符串排序,我们可以使用Arrays类的带两个参数的sort()方法,格式如下:publicstatic<T>voidsort(T[]a,Comparator<?superT>c)9.4.2Comparator<T>接口第一个参数a是任意类型的数组,第二个参数c是一个实现了java.util.Comparator接口的实例。Comparator<T>接口中声明了compare()抽象方法,如下所示。publicinterfaceComparator<T>{intcompare(Tfirst,Tsecond);//其他静态方法和默认方法}9.4.2Comparator<T>接口compare()方法用来比较它的两个参数对象。当第一个参数小于、等于、大于第二个参数时,该方法分别返回负整数、0、正整数。要想按长度比较字符串,可以定义一个类实现Comparator<String>接口。

privatestaticclassLengthComparatorimplementsComparator<String>{@Overridepublicintcompare(Stringa,Stringb){returna.length()-b.length();}}publicstaticvoidmain(String[]args){String[]ss={"this","is","a","test","string"};

LengthComparatorcomp=newLengthComparator();Arrays.sort(ss,comp);

//对数组ss按字符串长度排序for(Strings:ss){System.out.print(s+"");}}程序9.15ComparatorDemo.javapublicstaticvoidmain(String[]args){String[]s={"this","is","a","java","string"};Arrays.sort(s,newComparator<String>(){@Overridepublicintcompare(Stringfirst,Stringsecond){returnfirst.length()-second.length();

}});for(Stringstr:s){System.out.println(str);}}程序

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论