Java語言程序設(shè)計 課件 第9章 接口與內(nèi)部類_第1頁
Java語言程序設(shè)計 課件 第9章 接口與內(nèi)部類_第2頁
Java語言程序設(shè)計 課件 第9章 接口與內(nèi)部類_第3頁
Java語言程序設(shè)計 課件 第9章 接口與內(nèi)部類_第4頁
Java語言程序設(shè)計 課件 第9章 接口與內(nèi)部類_第5頁
已閱讀5頁,還剩61頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

Java語言程序設(shè)計第9章接口與內(nèi)部類

1接口23主要內(nèi)容Java語言程序設(shè)計(第4版)清華大學(xué)出版社2022接口的非抽象方法內(nèi)部類45接口示例案例:比較員工對象大小Java語言程序設(shè)計9.1接口接口(interface)定義了一種可以被類層次中的任何類實現(xiàn)的行為的契約,是常量、抽象方法、默認(rèn)方法、靜態(tài)方法和私有方法的集合。接口可以用來實現(xiàn)多重繼承。9.1.1接口定義接口的定義與類的定義類似,包括接口聲明和接口體兩部分。接口聲明使用interface關(guān)鍵字,格式如下:[public]interfaceInterfaceName[extendsSuperInterfaces]{//接口體定義}InterfaceName為接口名。extends表示該接口繼承(擴展)了哪些接口。如果接口使用public修飾,則該接口可以被所有的類使用,否則接口只能被同一個包中的類使用。9.1.1接口定義大括號內(nèi)為接口體,接口體中可以定義常量、抽象方法、默認(rèn)方法、靜態(tài)方法和私有方法等。下面代碼定義了一個簡單接口Eatable(可吃的)。publicinterfaceEatable{publicintSTATUS=100;publicabstractStringhowToEat();

//抽象方法的定義}9.1.1接口定義接口中的抽象方法只有聲明,沒有實現(xiàn)。抽象方法也可以省略修飾符,省略修飾符編譯器自動加上public、abstract,下面兩行代碼等價。publicabstractStringhowToEat();StringhowToEat();接口被看做是一種特殊的類型。與常規(guī)類一樣,每個接口都被編譯為獨立的字節(jié)碼文件。使用接口有點像使用抽象類。接口可以作為引用變量的數(shù)據(jù)類型或類型轉(zhuǎn)換的結(jié)果等。與抽象類一樣,不能用new運算符創(chuàng)建接口的實例。9.1.1接口定義在UML中,接口的表示與類圖類似,圖9-1是Eatable接口的UML圖,其中接口名上方使用<<interface>>表示接口,接口名和抽象方法名使用斜體表示。定義在接口中的任何變量都自動加上public、final、static屬性,因此它們都是常量,常量的定義可以省略修飾符,下面三行代碼效果相同。intSTATUS=100;publicintSTATUS=100;publicfinalstaticintSTATUS=100;9.1.2常量按照J(rèn)ava標(biāo)識符命名慣例,常量名都使用大寫字母命名。接口中的常量應(yīng)該使用接口名引用。不推薦在接口中定義常量,因為使用枚舉類型描述一組常量集合比接口中定義常量更好。實現(xiàn)接口就是實現(xiàn)接口中定義的抽象方法,這需要在類聲明中用implements子句來表示實現(xiàn)接口,一般格式如下:[public]classClassNameimplementsInterfaceList{//類體定義}9.1.3接口的實現(xiàn)一個類可以實現(xiàn)多個接口,這需要在implements子句中指定要實現(xiàn)的接口并用逗號分隔。在這種情況下如果把接口理解成特殊的類,那么這個類利用接口實際上實現(xiàn)了多繼承。一個類在實現(xiàn)某接口的抽象方法時,必須使用與接口完全相同的方法簽名,否則只是重載的方法而不是實現(xiàn)已有的抽象方法。接口方法的訪問修飾符都是public,所以類在實現(xiàn)方法時,必須顯式使用public修飾符,否則編譯器警告縮小了訪問控制范圍。下面的Mutton類實現(xiàn)了Eatable接口。9.1.3接口的實現(xiàn)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(){//一個默認(rèn)方法System.out.println("這是接口BB的默認(rèn)方法");}}程序9.4BB.javapackagecom.boda.xy;publicinterfaceCCextendsAA,BB{intNUM=3;//定義一個常量}程序9.5CC.java接口可以多繼承與類的繼承類似,子接口繼承父接口中的常量、抽象方法、默認(rèn)方法。在接口CC中,除本身定義的常量和各種方法外,它將繼承所有超接口中的常量和方法,因此,在接口CC中包含2個常量、2個抽象方法和一個默認(rèn)方法。與類的繼承不同的是,接口可以多繼承。9.1.4接口的繼承一個類要實現(xiàn)CC接口,它必須實現(xiàn)CC接口的兩個抽象方法,請看下面代碼。publicclassDDimplementsCC{//實現(xiàn)AA接口中的display方法publicvoiddisplay(){System.out.println("接口AA的display方法");}//實現(xiàn)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();//調(diào)用繼承來的默認(rèn)方法AAaa=newDD();aa.display();}一個類也可以實現(xiàn)多個接口,下面的AB類實現(xiàn)了AA接口和BB接口。publicclassABimplementsAA,BB{@Overridepublicvoiddisplay(){System.out.println("AA接口的display方法");}@Override

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

}}程序9.7AB.java接口也是一種引用類型,任何實現(xiàn)該接口的實例都可以存儲在該接口類型的變量中。AAaa=newDD();//向上自動類型轉(zhuǎn)換BBbb=newDD();CCcc=newDD();9.1.5接口類型的使用當(dāng)通過接口對象調(diào)用某個方法時,Java運行時系統(tǒng)確定該調(diào)用哪個類中的方法。

aa.display();//調(diào)用實現(xiàn)類的方法

bb.show();cc.print();//調(diào)用繼承的默認(rèn)方法

6.1.1課堂討論及訓(xùn)練Java語言程序設(shè)計(第4版)

QQ群:2886394861.設(shè)計一個名為Swimmable的接口,其中包含voidswim()方法,設(shè)計另一個名為Flyable的接口,其中包含voidfly()方法。2.定義一個Duck類實現(xiàn)上述兩個接口。3.定義測試類,演示接口類型的使用。Java語言程序設(shè)計9.2接口的非抽象方法在Java的早期版本中,接口的方法只能定義為抽象的。從Java8開始可以在接口中定義靜態(tài)方法和默認(rèn)方法。從Java9開始在接口中還可以定義私有方法。這三種方法都是具體實現(xiàn)的方法。下面來學(xué)習(xí)這幾種方法的定義。概述從Java8開始,可以在接口中定義靜態(tài)方法,與接口有關(guān)的靜態(tài)方法都可以在接口中定義,而不再需要輔助類。定義靜態(tài)方法使用static關(guān)鍵字,默認(rèn)的訪問修飾符是public。9.2.1靜態(tài)方法

publicinterfaceSS{intSTATUS=100;publicstaticvoiddisplay(){//靜態(tài)方法System.out.println(STATUS);}}可以給接口中任何方法提供一個默認(rèn)實現(xiàn),這稱為默認(rèn)方法(defaultmethod)。默認(rèn)方法需要使用default關(guān)鍵字定義。9.2.2默認(rèn)方法publicinterfaceBB{publicdefaultvoidprint(){//一個默認(rèn)方法System.out.println("這是接口BB的默認(rèn)方法");}}默認(rèn)方法可以被子接口和實現(xiàn)類繼承,但子接口中若定義相同的默認(rèn)方法,父接口的默認(rèn)方法被隱藏。默認(rèn)方法需要通過引用變量調(diào)用。從Java9開始,還可以在接口中定義私有方法。私有方法通常實現(xiàn)某種行為,這些行為可以被默認(rèn)方法調(diào)用。9.2.3私有方法也可以定義靜態(tài)私有方法,靜態(tài)私有方法可以被接口的靜態(tài)方法調(diào)用,也可以被默認(rèn)方法調(diào)用。如果使用默認(rèn)方法開發(fā)API,那么接口私有方法可能有助于實現(xiàn)其部分功能。publicinterfaceMyInterface{

staticprivatevoidinit2(){System.out.println("靜態(tài)私有方法");}publicstaticvoidm(){init2();}

privatevoidinit(){System.out.println("完成某些初始化操作");}voidnormalInterfaceMethod();defaultvoiddefaultMethod(){init();init2();}defaultvoidanotherDefaultMethod(){init();}}Java語言程序設(shè)計9.3內(nèi)部類Java語言允許在一個類(或接口)的內(nèi)部定義另一個類(接口、枚舉、記錄或注解等,這種類稱為內(nèi)部類(innerclass)。使用內(nèi)部類可以帶來如下好處:對只在一處使用的類進行分組;提高封裝性;增強代碼的可讀性和可維護性。有多種類型的內(nèi)部類。大致可分為:成員內(nèi)部類靜態(tài)內(nèi)部類匿名內(nèi)部類局部內(nèi)部類概述成員內(nèi)部類是沒有用static修飾且定義在外層類的類體中。下面程序在Outer類中定義了一個成員內(nèi)部類Inner。9.3.1成員內(nèi)部類publicclassOuter{privateintx=200;publicclassInner{inty=300;publicintcalculate(){returnx+y;}}publicvoidmakeInner(){Inneric=newInner();//創(chuàng)建內(nèi)部類對象System.out.println(ic.calculate());}程序9.8Outer.java這是一個內(nèi)部類publicstaticvoidmain(String[]args){varouter=newOuter();varinner=outer.newInner();System.out.println(inner.calculate());//輸出:500}內(nèi)部類編譯后將單獨生成一個類文件,如上述代碼編譯后將生成兩個類文件:Outer.class和Outer$InnerClass.class。在成員內(nèi)部類中可以定義自己的成員變量和方法(如calculate()),也可以定義自己的構(gòu)造方法。成員內(nèi)部類的訪問修飾符可以是private、public、protected或缺省。9.3.1成員內(nèi)部類在外層類的方法中(如makeInner)可以直接創(chuàng)建內(nèi)部類的實例。在外層類的外面要創(chuàng)建內(nèi)部類的實例必須先創(chuàng)建一個外層類的對象,因為內(nèi)部類對象對外層類對象有一個隱含的引用。創(chuàng)建內(nèi)部類對象也可以使用下面的語句實現(xiàn):varinner=newOuter().newInner();在使用成員內(nèi)部類時需要注意下面幾個問題:成員內(nèi)部類中不能定義static變量和static方法。成員內(nèi)部類也可以使用abstract和final修飾,其含義與其他類一樣。成員內(nèi)部類還可以使用private、public、protected或包可訪問修飾符。9.3.1成員內(nèi)部類靜態(tài)內(nèi)部類使用static修飾,靜態(tài)內(nèi)部類也稱嵌套類(nestedclass),靜態(tài)內(nèi)部類與成員內(nèi)部類的行為不同,下面是它們的不同之處:靜態(tài)內(nèi)部類中可以定義靜態(tài)成員,而成員內(nèi)部類不能。靜態(tài)內(nèi)部類只能訪問外層類的靜態(tài)成員。成員內(nèi)部類可以訪問外層類的實例成員和靜態(tài)成員。創(chuàng)建靜態(tài)內(nèi)部類的實例不需要先創(chuàng)建一個外層類的實例。相反,創(chuàng)建成員內(nèi)部類實例,必須先創(chuàng)建一個外層類的實例。9.3.2靜態(tài)內(nèi)部類publicclassOuter2{privatestaticintx=100;publicstaticclassInner2{privateStringy="hello";publicvoidinnerMethod(){System.out.println("xis"+x);//可以訪問外層類的靜態(tài)成員xSystem.out.println("yis"+y);}}publicstaticvoidmain(String[]args){Outer2.Inner2snc=newOuter2.Inner2();snc.innerMethod();}}程序9.9Outer2.java在類的內(nèi)部還可以定義內(nèi)部接口,內(nèi)部接口的隱含屬性是static的,當(dāng)然也可以指定。嵌套的類或接口可以有任何訪問修飾符,如public、protected、private以及缺省。在內(nèi)部類中還可以定義下一層的內(nèi)部類,形成類的多層嵌套。內(nèi)部接口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();

}定義類最終目的是創(chuàng)建一個類的實例,但如果某個類的實例只使用一次,可以將類的定義和實例的創(chuàng)建在一起完成,或者說在定義類的同時創(chuàng)建一個實例。以這種方式定義的沒有名字的類稱為匿名內(nèi)部類(anonymousinnerclass)。9.3.3匿名內(nèi)部類聲明和構(gòu)建匿名內(nèi)部類的一般格式如下:newTypeName(){/*此處為類體*/}匿名內(nèi)部類可以實現(xiàn)一個接口或繼承一個類,這里TypeName是匿名內(nèi)部類所實現(xiàn)的接口或繼承的類。如果實現(xiàn)一個接口,該類是Object類的直接子類。匿名類繼承一個類或?qū)崿F(xiàn)一個接口不需要使用extends或implements關(guān)鍵字。匿名內(nèi)部類不能同時繼承一個類和實現(xiàn)一個接口,也不能實現(xiàn)多個接口。9.3.3匿名內(nèi)部類由于匿名內(nèi)部類沒有名稱,所以類體中不能定義構(gòu)造方法。由于不知道類名,所以只能在定義類的同時用new關(guān)鍵字創(chuàng)建類的實例。實際上,匿名內(nèi)部類的定義、創(chuàng)建對象發(fā)生在同一個地方。另外,上式是一個表達式,它返回一個對象的引用,所以可以直接使用或?qū)⑵滟x給一個引用變量。TypeNameobj=newTypeName(){/*此處為類體*/};9.3.3匿名內(nèi)部類同樣,也可以將構(gòu)建的對象作為方法調(diào)用的參數(shù)。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.");}};//這里的分號是賦值語句的結(jié)束dog.eat();}}匿名內(nèi)部類的一個重要應(yīng)用是編寫JavaFX圖形界面的事件處理程序。如為按鈕對象button注冊事件處理器,就可以使用匿名內(nèi)部類。9.3.3匿名內(nèi)部類button.setOnAction(newEventHandler<ActionEvent>(){@Overridepublicvoidhandle(ActionEventevent){label.setText("你單擊了'確定'按鈕");}});可以在方法體或語句塊內(nèi)定義類。在方法體或語句塊(包括方法、構(gòu)造方法、局部塊、初始化塊或靜態(tài)初始化塊)內(nèi)部定義的類稱為局部內(nèi)部類(localinnerclass)。9.3.4局部內(nèi)部類局部內(nèi)部類不能視作外部類的成員,只對局部塊有效,如同局部變量一樣,在說明它的塊之外完全不能訪問,因此也不能有任何訪問修飾符。Java語言程序設(shè)計9.4接口示例Java類庫中也定義了許多接口,有些接口中沒有定義任何方法,這些接口稱為標(biāo)識接口,如java.lang包中定義的Cloneable接口、java.io包中的Serializable接口。概述有些接口中定義了若干方法,如java.lang包中的Comparable<T>接口中定義了comapreTo()方法,AutoClosable接口定義了close()方法,Runnable接口中定義了run()方法。要想比較類實例(如Circle類或Employee類)對象的大小,需要實現(xiàn)Comparable<T>接口。該接口的定義如下:9.4.1Comparable<T>接口packagejava.lang;publicinterfaceComparable<T>{intcompareTo(Tother);}如果希望一個類的對象能夠比較大小,類必須實現(xiàn)Comparable<T>接口的compareTo()方法。該方法實現(xiàn)當(dāng)前對象與參數(shù)對象比較,返回一個整數(shù)值。9.4.1Comparable<T>接口當(dāng)調(diào)用對象小于、等于、大于參數(shù)對象時,該方法分別返回負(fù)整數(shù)、0和正整數(shù)。按這種方法比較出的對象順序稱為自然順序(naturalorder)。下面程序說明了如何通過實現(xiàn)Comparable<T>接口對Circle類的對象根據(jù)其面積大小進行比較。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數(shù)組中3個Circle對象排序

Arrays.sort(circles);for(Circlec:circles)System.out.printf("%6.2f%n",c.getArea());}JavaAPI中許多類實現(xiàn)了Comparable<T>接口,如基本數(shù)據(jù)類型包裝類(Byte、Short、Integer、Long、Float、Double、Character、Boolean),F(xiàn)ile類、String類、LocalDate類,BigInteger類和BigDecimal類也實現(xiàn)了Comparable<T>接口,這些類的對象都可按自然順序排序。9.4.1Comparable<T>接口下面代碼比較兩個本地日期的大小。vard1=LocalDate.now();vard2=LocalDate.of(2022,10,1);System.out.println(pareTo(d2));//輸出:1假設(shè)需要根據(jù)長度而不是字典順序?qū)ψ址判?,我們可以使用Arrays類的帶兩個參數(shù)的sort()方法,格式如下:publicstatic<T>voidsort(T[]a,Comparator<?superT>c)9.4.2Comparator<T>接口第一個參數(shù)a是任意類型的數(shù)組,第二個參數(shù)c是一個實現(xiàn)了java.util.Comparator接口的實例。Comparator<T>接口中聲明了compare()抽象方法,如下所示。publicinterfaceComparator<T>{intcompare(Tfirst,Tsecond);//其他靜態(tài)方法和默認(rèn)方法}9.4.2Comparator<T>接口compare()方法用來比較它的兩個參數(shù)對象。當(dāng)?shù)谝粋€參數(shù)小于、等于、大于第二個參數(shù)時,該方法分別返回負(fù)整數(shù)、0、正整數(shù)。要想按長度比較字符串,可以定義一個類實現(xiàn)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);

//對數(shù)組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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論