Java面向對象程序設計(IDEA版) 課件 第8章接口與內部類_第1頁
Java面向對象程序設計(IDEA版) 課件 第8章接口與內部類_第2頁
Java面向對象程序設計(IDEA版) 課件 第8章接口與內部類_第3頁
Java面向對象程序設計(IDEA版) 課件 第8章接口與內部類_第4頁
Java面向對象程序設計(IDEA版) 課件 第8章接口與內部類_第5頁
已閱讀5頁,還剩105頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

面向對象程序設計第8章接口與內部類

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

//抽象方法的定義}8.1.1接口定義接口中的抽象方法只有聲明,沒有實現。抽象方法也可以省略修飾符,省略修飾符編譯器自動加上public、abstract,下面兩行代碼等價。publicabstractStringhowToEat();StringhowToEat();接口被看做是一種特殊的類型。與常規類一樣,每個接口都被編譯為獨立的字節碼文件。使用接口有點像使用抽象類。接口可以作為引用變量的數據類型或類型轉換的結果等。與抽象類一樣,不能用new運算符創建接口的實例。8.1.1接口定義在UML中,接口的表示與類圖類似,圖9-1是Eatable接口的UML圖,其中接口名上方使用<<interface>>表示接口,接口名和抽象方法名使用斜體表示。實現接口就是實現接口中定義的抽象方法,這需要在類聲明中用implements子句來表示實現接口,一般格式如下:[public]classClassNameimplementsInterfaceList{//類體定義}8.1.2接口的實現一個類可以實現多個接口,這需要在implements子句中指定要實現的接口并用逗號分隔。在這種情況下如果把接口理解成特殊的類,那么這個類利用接口實際上實現了多繼承。一個類在實現某接口的抽象方法時,必須使用與接口完全相同的方法簽名,否則只是重載的方法而不是實現已有的抽象方法。接口方法的訪問修飾符都是public,所以類在實現方法時,必須顯式使用public修飾符,否則編譯器警告縮小了訪問控制范圍。下面的Mutton類實現了Eatable接口。8.1.2接口的實現packagecom.boda.xy;publicclassMuttonimplementsEatable{@OverridepublicStringhowToEat(){return"烤羊肉串";

}}程序8-2Mutton.java一個接口可以繼承一個或多個接口。下面代碼定義了三個接口,其中CC接口繼承了AA接口和BB接口。8.1.3接口的繼承packagecom.boda.xy;interfaceAA{intSTATUS=100;//常量聲明publicabstractvoiddisplay();//一個抽象方法}程序8-3CC.javainterfaceBB{publicabstractvoidshow();//一個抽象方法publicdefaultvoidprint(){//一個默認方法System.out.println("這是接口BB的默認方法");}}publicinterfaceCCextendsAA,BB{intNUM=3;//定義一個常量}接口可以多繼承與類的繼承類似,子接口繼承父接口中的常量、抽象方法、默認方法。在接口CC中,除本身定義的常量和各種方法外,它將繼承所有超接口中的常量和方法,因此,在接口CC中包含2個常量、2個抽象方法和一個默認方法。與類的繼承不同的是,接口可以多繼承。8.1.3接口的繼承一個類要實現CC接口,它必須實現CC接口的兩個抽象方法,請看下面代碼。publicclassDDimplementsCC{//實現AA接口中的display方法publicvoiddisplay(){System.out.println("接口AA的display方法");}//實現BB接口中的show方法publicvoidshow(){System.out.println("接口BB的show方法");}}程序8-4DD.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方法");

}}接口也是一種引用類型,任何實現該接口的實例都可以存儲在該接口類型的變量中。AAaa=newDD();//向上自動類型轉換BBbb=newDD();CCcc=newDD();8.1.4接口類型的使用當通過接口對象調用某個方法時,Java運行時系統確定該調用哪個類中的方法。

aa.display();//調用實現類的方法

bb.show();cc.print();//調用繼承的默認方法

定義在接口中的任何變量都自動加上public、final、static屬性,因此它們都是常量,常量的定義可以省略修飾符,下面三行代碼效果相同。intSTATUS=100;publicintSTATUS=100;publicfinalstaticintSTATUS=100;8.1.5常

量按照Java標識符命名慣例,常量名都使用大寫字母命名。接口中的常量應該使用接口名引用。不推薦在接口中定義常量,因為使用枚舉類型描述一組常量集合比接口中定義常量更好。6.1.1課堂討論及訓練面向對象程序設計(Java語言描述微課版基于IntelliJIDEA)1.設計一個名為Swimmable的接口,其中包含voidswim()方法,設計另一個名為Flyable的接口,其中包含voidfly()方法。2.定義一個Duck類實現上述兩個接口。3.定義測試類,演示接口類型的使用。面向對象程序設計8.2接口方法在Java的早期版本中,接口的方法只能定義為抽象的。從Java8開始可以在接口中定義靜態方法和默認方法。從Java9開始在接口中還可以定義私有方法。這三種方法都是具體實現的方法。下面來學習這幾種方法的定義。概述可以給接口中任何方法提供一個默認實現,這稱為默認方法(defaultmethod)。默認方法需要使用default關鍵字定義。8.2.1默認方法publicinterfaceBB{publicdefaultvoidprint(){//一個默認方法System.out.println("這是接口BB的默認方法");}}默認方法可以被子接口和實現類繼承,但子接口中若定義相同的默認方法,父接口的默認方法被隱藏。默認方法需要通過引用變量調用。從Java9開始,還可以在接口中定義私有方法。私有方法通常實現某種行為,這些行為可以被默認方法調用。8.2.2私有方法也可以定義靜態私有方法,靜態私有方法可以被接口的靜態方法調用,也可以被默認方法調用。如果使用默認方法開發API,那么接口私有方法可能有助于實現其部分功能。publicinterfaceMyInterface{

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

privatevoidinit(){System.out.println("完成某些初始化操作");}voidnormalInterfaceMethod();defaultvoiddefaultMethod(){init();init2();}defaultvoidanotherDefaultMethod(){init();}}從Java8開始,可以在接口中定義靜態方法,與接口有關的靜態方法都可以在接口中定義,而不再需要輔助類。定義靜態方法使用static關鍵字,默認的訪問修飾符是public。8.2.3靜態方法

publicinterfaceSS{intSTATUS=100;publicstaticvoiddisplay(){//靜態方法System.out.println(STATUS);}}面向對象程序設計8.3接口示例Java類庫中也定義了許多接口,有些接口中沒有定義任何方法,這些接口稱為標識接口,如java.lang包中定義的Cloneable接口、java.io包中的Serializable接口。概述有些接口中定義了若干方法,如java.lang包中的Comparable<T>接口中定義了comapreTo()方法,AutoClosable接口定義了close()方法,Runnable接口中定義了run()方法。要想比較類實例(如Circle類或Employee類)對象的大小,需要實現Comparable<T>接口。該接口的定義如下:8.3.1Comparable<T>接口packagejava.lang;publicinterfaceComparable<T>{intcompareTo(Tother);}如果希望一個類的對象能夠比較大小,類必須實現Comparable<T>接口的compareTo()方法。該方法實現當前對象與參數對象比較,返回一個整數值。8.3.1Comparable<T>接口當調用對象小于、等于、大于參數對象時,該方法分別返回負整數、0和正整數。按這種方法比較出的對象順序稱為自然順序(naturalorder)。下面程序說明了如何通過實現Comparable<T>接口對Circle類的對象根據其面積大小進行比較。publicclassCircleimplementsComparable<Circle>{privatedoubleradius;publicCircle(){}publicCircle(doubleradius){this.radius=radius;}publicdoublegetPerimeter(){//求周長方法return2*radius*Math.PI;}程序8-5Circle.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>接口,這些類的對象都可按自然順序排序。8.3.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)8.3.2Comparator<T>接口第一個參數a是任意類型的數組,第二個參數c是一個實現了java.util.Comparator接口的實例。Comparator<T>接口中聲明了compare()抽象方法,如下所示。publicinterfaceComparator<T>{intcompare(Tfirst,Tsecond);//其他靜態方法和默認方法}8.3.2Comparator<T>接口compare()方法用來比較它的兩個參數對象。當第一個參數小于、等于、大于第二個參數時,該方法分別返回負整數、0、正整數。要想按長度比較字符串,可以定義一個類實現Comparator<String>接口。

publicclassLengthComparatorimplementsComparator<String>{@Overridepublicintcompare(Stringfirst,Stringsecond){returnfirst.length()-second.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+"");}}程序8-6LengthComparator.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);}}面向對象程序設計8.4案例:比較員工對象大小默認情況下,類的實例不能比較大小。要比較實例,類應該實現Comparable<T>接口的compareTo()方法。本案例要求定義Employee使它能夠根據員工號(整型id字段值)進行比較,id小的員工排在前面。問題描述創建一個包含三個元素的Employee數組,使用Arrays類的sort()方法對數組元素排序。然后輸出數組元素,查看Employee對象是否按id從小到大排序。定義一個比較器類AgeComparator,使其實現Comparator<T>接口的compare()方法,在Arrays.sort()方法中指定該比較器時要求能夠根據員工的年齡(沒有年齡字段,但是有出生日期字段birthday)進行比較,年齡大的員工排在前面。(1)要使Employee類能夠比較大小,定義類需要實現Comparable接口,這樣比較大小得出的順序成為自然順序。設計思路@OverridepublicintcompareTo(Employeeemployee){ if(getId()>employee.getId()) return1; elseif(getId()<employee.getId()) return-1; else return0;} (2)類對象還可以按其他方式比較大小,這時需要定義比較器,即實現Comparator<T>接口。下面代碼按員工出生日期升序比較。設計思路@Overridepublicintcompare(Employeefirst,Employeesecond){if(first.getBirthday().isBefore(second.getBirthday())){ return-1;}elseif(second.getBirthday().isBefore(first.getBirthday())){ return1;}else{ return0;}}面向對象程序設計8.5記錄類型在Java程序開發中,我們經常需要定義一些數據類,比如與數據庫表交互的JavaBeans類或POJO類,這些類通常使用字段表示數據,然后我們要為該類定義構造方法,為字段定義訪問方法和修改方法。這就需要程序員編寫大量的代碼。記錄類型從Java16開始,如果要定義這樣的類,可以使用record關鍵字將它定義為一個記錄類型。這種數據類型提供了一種緊湊的語法來聲明一種主要用于保存數據的類。假設定義一個Customer記錄類型,它帶兩個字段name和address,那么該類可能需要如下定義。packagecom.boda.xy;publicrecordCustomer(Stringname,Stringaddress){//這里可以定義記錄類型的成員}這里,類型名后面是一對括號,里面是字段的聲明,這相當于定義一個構造方法。記錄類型與其他類型一樣被編譯成類(.class)文件。對于記錄類型,編譯器將自動添加構造方法、equals()方法、hashCode()方法和toString()方法,并且為每個實例變量添加訪問方法(但不提供修改方法)。程序11.1Customer.java如果我們反編譯Customer.class文件,可得到類似下面的代碼。publicfinalclassCustomerextendsjava.lang.Record{privatefinaljava.lang.Stringname;privatefinaljava.lang.Stringaddress;publicCustomer(java.lang.Stringname,java.lang.Stringaddress){/*編譯的代碼*/}publicjava.lang.Stringname()

{/*編譯的代碼*/}publicjava.lang.Stringaddress()

{/*編譯的代碼*/}publicfinaljava.lang.StringtoString()

{/*編譯的代碼*/}publicfinalinthashCode()

{/*編譯的代碼*/}publicfinalbooleanequals(java.lang.Objecto)

{/*編譯的代碼*/}可以看到,聲明的Customer類繼承了java.lang.Record類,Customer類和它的兩個成員被聲明為final,也就是記錄類型不能被繼承,成員也不能被修改。記錄類型編譯器自動為它添加構造方法、equals()方法、hashCode()方法和toString()方法,并且為實例變量添加訪問方法。注意,這里的訪問方法名為實例名,如name()、address()等,而不是getName()這種形式的。publicclassCustomerDemo{publicstaticvoidmain(String[]args){varcustomer=newCustomer("張明月","北京市海淀區");varcustomer2=newCustomer("李大海","上海市科技路20號");System.out.println("姓名:"+customer.name());System.out.println("地址:"+customer.address());

System.out.println(customer.toString());System.out.println(customer.equals(customer2));System.out.println(customer.hashCode());System.out.println(customer2.hashCode());}}程序11.2CustomerDemo.java在記錄的主體中,還可以聲明static成員、構造方法和實例方法,例如:publicCustomer(Stringname){this(name,null);}記錄類型publicstaticStringinfo="客戶";publicstaticvoidshow(){System.out.println("顯示:"+info);}自定義構造方法必須明確調用帶參數構造方法自定義靜態變量和靜態方法publicvoidshowName(){System.out.println("姓名:"+name);}記錄類型【注意】

不能在記錄類型中聲明實例變量,但可以聲明靜態變量。【注意】

記錄類型字段的訪問器名是“屬性名()”,而不是getXxx(),例如,假設記錄類型有一個name屬性,則它的訪問器為name(),而不是getName()。此外,記錄類型沒有修改方法,也就是沒有類似的setName()方法。實例方法在記錄體中還可以覆蓋超類Record中定義的方法,下面代碼覆蓋了toString()方法和hashCode()方法。記錄類型@OverridepublicStringtoString(){ return"姓名:"+name+",地址:"+address;} @OverridepublicinthashCode(){ returnObjects.hash(name,address);}在記錄類型中用戶還可以定義自己的方法和構造方法,但通常不這樣做。記錄類型主要是解決用于存儲數據的普通類的一個常見問題。總結下面對記錄類型做一簡單總結:記錄類型默認繼承了java.lang.Record類,不能顯式繼承其他類。記錄類型是final的,即它不可以被繼承。每個成員變量都被加上privatefinal,對象創建后它們就不可變。每個成員變量都提供了public訪問方法,如name(),但不提供修改方法。提供了帶所有參數的構造方法、toString()方法、equals()方法和hashCode()方法。面向對象程序設計8.6枚舉類型在實際應用中,有些數據的取值被限定在幾個確定的值之內。例如,一年有4個季度,一周有7天、一副紙牌有4種花色等。對這種類型的數據可以定義為枚舉類型。8.6.1枚舉類型的定義枚舉類型是一種特殊的引用類型,它的聲明和使用與類和接口有類似的地方。枚舉類型的聲明使用enum關鍵字。下面程序定義了一個名為Direction的枚舉類型:

publicenumDirection{EAST,SOUTH,WEST,NORTH;}編譯后產生一個Direction.class類文件枚舉類型都隱含地繼承了java.lang.Enum抽象類,Enum類又是Object類的子類,同時實現了Comparable接口。每個枚舉類型都包含了若干方法,下面是一些常用的。

staticE[]values()

staticEvalueOf(Stringname)

finalintcompareTo(Eo)

finalStringname()

finalintordinal()8.6.2枚舉類型的方法packagecom.boda.xy;publicenumDirection{EAST,SOUTH,WEST,NORTH;}程序8-12Direction.javapublicstaticvoidmain(String[]args){//聲明一個枚舉類型變量,并用一個枚舉賦值varleft=Direction.WEST;System.out.println(left);//輸出:WEST//輸出每個枚舉對象及序號for(Directiond:Direction.values()){System.out.println(()+",序號"+d.ordinal());}}程序8-13DirectionDemo.java枚舉類型有一個特別實用的特性,它可以在switch語句中使用。java.time.DayOfWeek是一個枚舉類型,其中包括一周的7天,分別為MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY和SUNDAY,序號從0到6。EnumSwitch.java程序在switch結構中使用DayOfWeek枚舉。8.6.2在switch中使用枚舉的publicstaticvoiddescribe(DayOfWeekday){switch(day){caseMONDAY->System.out.println("Mondaysarebad.");caseFRIDAY->System.out.println("Fridaysarebetter.");caseSATURDAY,SUNDAY->System.out.println("Weekendsarebest.");default->System.out.println("Midweekdaysareso-so.");}}程序8-14EnumSwitch.javapublicstaticvoidmain(String[]args){varfirstDay=DayOfWeek.MONDAY;describe(firstDay);varthirdDay=DayOfWeek.WEDNESDAY;describe(thirdDay);varseventhDay=DayOfWeek.SUNDAY;describe(seventhDay);}在枚舉類型的聲明中,除了枚舉常量外還可以聲明構造方法,成員變量和其他方法。下面程序定義了Color枚舉,它包含4種顏色。8.6.3枚舉類型的構造方法publicenumColor{

RED("紅色",1),GREEN("綠色",2),WHITE("白色",3),YELLOW("黃色",4);

//成員變量privateStringname;privateintindex;

//構造方法privateColor(Stringname,intindex){=name;this.index=index;

}程序8-15Color.java

//普通方法publicstaticStringgetName(intindex){for(Colorc:Color.values()){if(c.getIndex()==index){return;

}

}returnnull;

}//getter和setter方法publicStringgetName(){returnname;

}publicvoidsetName(Stringname){=name;

}publicintgetIndex(){returnindex;

}publicvoidsetIndex(intindex){this.index=index;

}

//覆蓋方法@OverridepublicStringtoString(){return+"_"+this.index;

}publicstaticvoidmain(String[]args){Colorc=Color.RED;//自動調用構造方法System.out.println(c.toString());//輸出:1-紅色

}面向對象程序設計8.7內部類Java語言允許在一個類(或接口)的內部定義另一個類(接口、枚舉、記錄或注解等,這種類稱為內部類(innerclass)。使用內部類可以帶來如下好處:對只在一處使用的類進行分組;提高封裝性;增強代碼的可讀性和可維護性。有多種類型的內部類。大致可分為:成員內部類靜態內部類匿名內部類局部內部類概述成員內部類是沒有用static修飾且定義在外層類的類體中。下面程序在Outer類中定義了一個成員內部類Inner。8.7.1成員內部類publicclassOuter{privateintx=200;publicclassInner{inty=300;publicintcalculate(){returnx+y;}}publicvoidmakeInner(){Inneric=newInner();//創建內部類對象System.out.println(ic.calculate());}程序8-19Outer.java這是一個內部類publicstaticvoidmain(String[]args){varouter=newOuter();varinner=outer.newInner();System.out.println(inner.calculate());//輸出:500}內部類編譯后將單獨生成一個類文件,如上述代碼編譯后將生成兩個類文件:Outer.class和Outer$InnerClass.class。在成員內部類中可以定義自己的成員變量和方法(如calculate()),也可以定義自己的構造方法。成員內部類的訪問修飾符可以是private、public、protected或缺省。8.7.1成員內部類在外層類的方法中(如makeInner)可以直接創建內部類的實例。在外層類的外面要創建內部類的實例必須先創建一個外層類的對象,因為內部類對象對外層類對象有一個隱含的引用。創建內部類對象也可以使用下面的語句實現:varinner=newOuter().newInner();在使用成員內部類時需要注意下面幾個問題:成員內部類中不能定義static變量和static方法。成員內部類也可以使用abstract和final修飾,其含義與其他類一樣。成員內部類還可以使用private、public、protected或包可訪問修飾符。8.7.1成員內部類靜態內部類使用static修飾,靜態內部類也稱嵌套類(nestedclass),靜態內部類與成員內部類的行為不同,下面是它們的不同之處:靜態內部類中可以定義靜態成員,而成員內部類不能。靜態內部類只能訪問外層類的靜態成員。成員內部類可以訪問外層類的實例成員和靜態成員。創建靜態內部類的實例不需要先創建一個外層類的實例。相反,創建成員內部類實例,必須先創建一個外層類的實例。8.7.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();}}程序8-20Outer2.java在類的內部還可以定義內部接口,內部接口的隱含屬性是static的,當然也可以指定。嵌套的類或接口可以有任何訪問修飾符,如public、protected、private以及缺省。在內部類中還可以定義下一層的內部類,形成類的多層嵌套。內部接口定義類最終目的是創建一個類的實例,但如果某個類的實例只使用一次,可以將類的定義和實例的創建在一起完成,或者說在定義類的同時創建一個實例。以這種方式定義的沒有名字的類稱為匿名內部類(anonymousinnerclass)。8.7.3匿名內部類聲明和構建匿名內部類的一般格式如下:newTypeName(){/*此處為類體*/}匿名內部類可以實現一個接口或繼承一個類,這里TypeName是匿名內部類所實現的接口或繼承的類。如果實現一個接口,該類是Object類的直接子類。匿名類繼承一個類或實現一個接口不需要使用extends或implements關鍵字。匿名內部類不能同時繼承一個類和實現一個接口,也不能實現多個接口。8.7.3匿名內部類由于匿名內部類沒有名稱,所以類體中不能定義構造方法。由于不知道類名,所以只能在定義類的同時用new關鍵字創建類的實例。實際上,匿名內部類的定義、創建對象發生在同一個地方。另外,上式是一個表達式,它返回一個對象的引用,所以可以直接使用或將其賦給一個引用變量。TypeNameobj=newTypeName(){/*此處為類體*/};8.7.3匿名內部類同樣,也可以將構建的對象作為方法調用的參數。someMethod(newTypeName(){/*此處為類體*/});interfacePrintable{publicabstractvoidprint(Stringmessage);}publicclassPrintableTest{publicstaticvoidmain(String[]args){Printableprinter=newPrintable(){@Overridepublicvoidprint(Stringmessage){System.out.println(message);}};printer.print("這是惠普打印機");}}程序8-21PrintableTest.javaclassAnimal{publicvoideat(){System.out.println("Ilikeeatanything.");}}程序8-22AnimalTest.javapublicclassAnimalTest{publicstaticvoidmain(String[]args){Animaldog=newAnimal(){//繼承Animal類@Overridepublicvoideat(){System.out.println("Ilikeeatbones.");}};//這里的分號是賦值語句的結束dog.eat();}}匿名內部類的一個重要應用是編寫JavaFX圖形界面的事件處理程序。如為按鈕對象button注冊事件處理器,就可以使用匿名內部類。8.7.3匿名內部類button.setOnAction(newEventHandler<ActionEvent>(){@Overridepublicvoidhandle(ActionEventevent){label.setText("你單擊了'確定'按鈕");}});可以在方法體或語句塊內定義類。在方法體或語句塊(包括方法、構造方法、局部塊、初始化塊或靜態初始化塊)內部定義的類稱為局部內部類(localinnerclass)。8.7.4局部內部類局部內部類不能視作外部類的成員,只對局部塊有效,如同局部變量一樣,在說明它的塊之外完全不能訪問,因此也不能有任何訪問修飾符。面向對象程序設計8.8注解類型注解以結構化的方式為程序元素提供信息,這些信息能夠被外部工具(編譯器、解釋器等)自動處理。注解類型注解有許多用途,其中包括:

為編譯器提供信息。

編譯時或部署時處理。

運行時處理。區分注解類型和注解注解類型是一種特殊的接口類型,像使用類一樣,要使用注解必須先定義注解類型(也可以使用語言本身提供的注解類型)。8.8.1注解概述注解是注解類型的一個實例。就像接口一樣,注解類型也有名稱和成員。注解中包含的信息采用“鍵/值”對的形式,可以有零或多個“鍵/值”對,并且每個鍵有一個特定類型。它可以是一個Stirng、int或其他Java類型。沒有“鍵/值”對的注解類型稱作標記注解類型。如果注解只需要一個“鍵/值”對,則稱為單值注解類型。8.8.1注解概述在Java程序中為程序元素標注注解的語法如下:

@AnnotationType或者

@AnnotationType(elementValuePairs)對沒有默認值的元素,都應該以name=value的形式對元素初始化。如果注解類型是標記注解類型(無元素),或者所有的元素都具有默認值,那么就可以省略初始化器列表。8.8.1注解概述如果注解類型只有一個元素,可以使用縮略的形式對注解元素初始化。例如,假設注解類型Copyright只有一個String類型的元素,用它注解程序元素時就可以寫作:

@Copyright("copyright2010-2015")8.8.1注解概述可以給Java包、類型(類、接口、枚舉)、構造方法、方法、成員變量、參數及局部變量進行標注。例如,可以給一個Java類進行標注,以便阻止javac程序可能發出的警告,也可以對一個要覆蓋的方法進行標注,讓編譯器知道你是要覆蓋這個方法而不是重載它。這里介紹Java語言規范中定義的3個注解類型,它們是供編譯器使用的。它們定義在java.lang包中,分別為@Override@Deprecated@SuppressWarnings8.8.2標準注解@Override是一個標記注解類型,可以用在一個方法的聲明中,它告訴編譯器這個方法要覆蓋父類中的某個方法。使用該注解可以防止程序員在覆蓋某個方法時出錯。例如,考慮下面的Parent類:

classParent{

publicdoublecalculate(doublex,doubley){

returnx*y;

}}假設現在要擴展Parent類,并覆蓋它的calculate()方法。下面是Parent類的一個子類:

classChildextendsParent{

publicintcalculate(intx,inty){

return(x+1)*y;

}}Child類可以編譯。然而,Child類中的calculate()方法并沒有覆蓋Parent中的方法,因為它的參數是2個int型,而不是2個double型。使用Override注解就可以很容易防止這類錯誤。每當你想要覆蓋一個方法時,就在這個方法前聲明Override注解類型:classChildextendsParent{

@Override

publicintcalculate(intx,inty){

return(x+1)*y;

}}@Deprecated是一個標記注解類型,可以應用于某個方法或某個類型,指明方法或類型已被棄用。警告代碼用戶不應該使用或者覆蓋該方法,或者不該使用或擴展該類型。一個方法或類型被標記棄用通常是因為有了更好的方法或類型。2.@Deprecated注解下面代碼使用了Deprecated注解。@DeprecatedpublicvoidbadMethod(){

System.out.println("Deprecated");

}

publicstaticvoidmain(String[]args){

DeprecatedDemo

dd=newDeprecatedDemo();

dd.badMethod();}在Eclipse中棄用的方法加刪除線調用被棄用的方法也加刪除線@SuppressWarnings注解指示編譯器阻止某些類型的警告,具體警告類型可以用初始化該注解的字符串來定義。該注解可應用于類型、構造方法、方法、成員變量、參數以及局部變量。它的用法是傳遞一個String數組,其中包含需要阻止的警告。語法如下:

SuppressWarnings(value={string-1,…,string-n})3.@SuppressWarnings注解以下是Sup

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論