java学习笔记8--接口总结
接著前面的學(xué)習(xí):
java學(xué)習(xí)筆記7--抽象類與抽象方法
java學(xué)習(xí)筆記6--類的繼承、Object類
java學(xué)習(xí)筆記5--類的方法?
java學(xué)習(xí)筆記4--對象的初始化與回收
java學(xué)習(xí)筆記3--類與對象的基礎(chǔ)?
java學(xué)習(xí)筆記2--數(shù)據(jù)類型、數(shù)組
java學(xué)習(xí)筆記1--開發(fā)環(huán)境平臺總結(jié)
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note8.html,轉(zhuǎn)載請注明源地址。
生活中的接口:
什么是接口?
一個Java接口是一些方法特征的集合,但沒有方法的實現(xiàn)。
在類中實現(xiàn)接口可以使用關(guān)鍵字implements,其基本格式如下:
[修飾符] class <類名> [extends 父類名] [implements 接口列表]{
}
修飾符:可選參數(shù),用于指定類的訪問權(quán)限,可選值為public、abstract和final。
類名:必選參數(shù),用于指定類的名稱,類名必須是合法的Java標(biāo)識符。一般情況下,要求首字母大寫。
extends 父類名:可選參數(shù),用于指定要定義的類繼承于哪個父類。當(dāng)使用extends關(guān)鍵字時,父類名為必選參數(shù)。
implements 接口列表:可選參數(shù),用于指定該類實現(xiàn)的是哪些接口。當(dāng)使用implements關(guān)鍵字時,接口列表為必選參數(shù)。當(dāng)接口列表中存在多個接口名時,各個接口名之間使用逗號分隔。
實現(xiàn)上面例子中的接口:
public interface PCI { //java接口,相當(dāng)于主板上的PCI插槽的規(guī)范public void start();public void stop(); }Java接口中定義的方法在不同的地方被實現(xiàn),可以具有完全不同的行為:
//聲卡、網(wǎng)卡都實現(xiàn)了PCI插槽的規(guī)范,但行為完全不同 class SoundCard implements PCI { public void start() {System.out.println("SoundCard start...");}public void stop() {System.out.println("Sound stop!");} } class NetworkCard implements PCI {public void start() {System.out.println("NetworkCard send...");}public void stop() {System.out.println("Send stop!");} }可以使用Java接口標(biāo)識類型。運行時,根據(jù)實際創(chuàng)建的對象類型調(diào)用相應(yīng)的方法實現(xiàn):
public class javatest {public static void main(String[] args) {PCI nc = new NetworkCard();PCI sc = new SoundCard();nc.start();sc.start();} }運行結(jié)果:
NetworkCard send...
SoundCard start...
為什么需要Java接口?
例子:為學(xué)校各中心開發(fā)這樣一個小系統(tǒng),包含類型:教員、中心、打印機,具體要求如下:
1、教員、以及中心都具有方法:輸出詳細信息
2、中心具有屬性:打印機,能夠通過中心的打印機打印教員或中心的詳細信息
3、系統(tǒng)要具備良好的可擴展性與可維護性
先看方案1:
public class Teacher {//輸出教員的詳細信息public String detail() {return “I am a teacher!"; } } public class Printer {public void print(String content) {System.out.println("start printing:"); System.out.println(content);} } public class ggSchool {private Printer printer = new Printer();//輸出學(xué)校的詳細信息public String detail() {return “this is ggSchool"; }//使用打印機打印教員信息public void print(Teacher t){printer.print(t.detail());}//使用打印機打印學(xué)院信息public void print(ggSchool s){printer.print(s.detail());} }那么,問題來了:
每增加一種新類型,都需要增加相應(yīng)的print方法,程序的可擴展性及可維護性極差,這不符合系統(tǒng)的要求
先看方案2(使用接口):
教師、中心都存在一個共同的方法特征:detail,它們對detail方法有各自不同的實現(xiàn)——這完全符合Java接口的定義
代碼如下:
public interface Introduceable {public String detail(); } public class Teacher implements Introduceable {//輸出教員的詳細信息public String detail() {return “I am a teacher!"; } } public class ggSchool implements Introduceable {private Printer printer = new Printer();//輸出學(xué)校的詳細信息public String detail() {return “this is ggSchool"; }public void print(Introduceable intro) { //使用print方法時,參數(shù)可以是任何Introduceable接口的實現(xiàn)類的對象,//不必再為不同的類型建立不同的print方法了 printer.print(intro.detail());} } public class Printer {public void print(String content) {System.out.println("start printing:"); System.out.println(content);} }通過Java接口,我們同樣可以享受到多態(tài)性的好處,大大提高了程序的可擴展性及可維護性?
什么是面向接口編程?
開發(fā)系統(tǒng)時,主體構(gòu)架使用接口,接口構(gòu)成系統(tǒng)的骨架,這樣就可以通過更換接口的實現(xiàn)類來更換系統(tǒng)的實現(xiàn)
升級上面的系統(tǒng),要求:打印機有多種類型,比如:黑白打印機、彩色打印機等
學(xué)院可能配備其中任意一款打印機,負責(zé)打印教員、或者學(xué)院的詳細信息
系統(tǒng)要具備良好的可擴展性與可維護性
第一步:抽象出Java接口
1、分析:
黑白、彩色打印機都存在一個共同的方法特征:print
黑白、彩色打印機對print方法有各自不同的實現(xiàn)
2、結(jié)論:
抽象出Java接口PrinterFace,在其中定義方法print
3、具體實現(xiàn):
public interface PrinterFace {public void print(String content); } 第二步:實現(xiàn)Java接口1、分析:
已經(jīng)抽象出Java接口PrinterFace,并在其中定義了print方法黑白、彩色打印機對print方法有各自不同的實現(xiàn)
2、結(jié)論:黑白、彩色打印機都實現(xiàn)PrinterFace接口,各自實現(xiàn)print方法
3、具體實現(xiàn):
public class ColorPrinter implements PrinterFace {public void print(String content) {System.out.println("彩色打印:");System.out.println(content);} } public class BlackPrinter implements PrinterFace {public void print(String content) {System.out.println("黑白打印:");System.out.println(content);} }第三步:使用Java接口
1、分析:主體構(gòu)架使用接口, 讓接口構(gòu)成系統(tǒng)的骨架
2、結(jié)論:更換實現(xiàn)接口的類就可以更換系統(tǒng)的實現(xiàn)
3、具體實現(xiàn):
public class ggSchool implements Introduceable{private PrinterFace printer; //打印機public void setPrinter(PrinterFace p) {this.printer = p;}public String detail() {return "this is ggSchool!";}public void print(Introduceable intro){printer.print(intro.detail());} } public class Test {public static void main(String[] args) {// 創(chuàng)建學(xué)院實例ggSchool school=new ggSchool();//為該學(xué)院配備黑白打印機school.setPrinter(new BlackPrinter());school.print(school); //為該學(xué)院配備彩色打印機school.setPrinter(new ColorPrinter());school.print(school);} }抽象類與接口
抽象類的子類必須覆蓋所有的抽象方法后才能被實例化,否則這個子類還是個抽象類。
如果一個抽象類中的所有方法都是抽象的,就可以將這個類用另外一種方式來定義,也就是接口定義。
抽象方法只需聲明,不需實現(xiàn)。
接口是抽象方法和常量值的定義的集合。
從本質(zhì)上講,接口是一種特殊的抽象類。這種抽象類中包含常量和方法的定義,而沒有變量和方法的實現(xiàn)。例如
注意:在接口的定義中,所有的成員都是public訪問類型的,而不論是否用public關(guān)鍵字修飾;接口里的變量都是用public static final標(biāo)識的,所以,接口中定義的變量就是全局靜
態(tài)常量。
我們可以定義一個新的接口,用extends關(guān)鍵字去繼承一個已有的接口。注意:只能接口繼承接口,類不能繼承接口。
一個類只能用implements關(guān)鍵字去實現(xiàn)一個接口中的所有方法
一個類可以在繼承一個父類的同時,實現(xiàn)一個或多個接口,extends關(guān)鍵字必須位于implements關(guān)鍵字之前,如我們可以這樣定義:
class classA {//... } public interface Interface1{//... } public interface Interface2{//... } class classB extends classA implements Interface1 Interface2{//... }抽象類和接口的區(qū)別
1.語法層面上的區(qū)別
1)抽象類可以提供成員方法的實現(xiàn)細節(jié),而接口中只能存在public abstract 方法;
2)抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是public static final類型的;
3)接口中不能含有靜態(tài)代碼塊以及靜態(tài)方法,而抽象類可以有靜態(tài)代碼塊和靜態(tài)方法;
4)一個類只能繼承一個抽象類,而一個類卻可以實現(xiàn)多個接口。
2.設(shè)計層面上的區(qū)別
1)抽象類是對一種事物的抽象,即對類抽象,而接口是對行為的抽象。抽象類是對整個類整體進行抽象,包括屬性、行為,但是接口卻是對類局部(行為)進行抽象。舉個簡單的例子,飛機和鳥是不同類的事物,但是它們都有一個共性,就是都會飛。那么在設(shè)計的時候,可以將飛機設(shè)計為一個類Airplane,將鳥設(shè)計為一個類Bird,但是不能將 飛行 這個特性也設(shè)計為類,因此它只是一個行為特性,并不是對一類事物的抽象描述。此時可以將 飛行 設(shè)計為一個接口Fly,包含方法fly( ),然后Airplane和Bird分別根據(jù)自己的需要實現(xiàn)Fly這個接口。然后至于有不同種類的飛機,比如戰(zhàn)斗機、民用飛機等直接繼承Airplane即可,對于鳥也是類似的,不同種類的鳥直接繼承Bird類即可。從這里可以看出,繼承是一個 "是不是"的關(guān)系,而接口實現(xiàn)則是 "有沒有"的關(guān)系。如果一個類繼承了某個抽象類,則子類必定是抽象類的種類,而接口實現(xiàn)則是有沒有、具備不具備的關(guān)系,比如鳥是否能飛(或者是否具備飛行這個特點),能飛行則可以實現(xiàn)這個接口,不能飛行就不實現(xiàn)這個接口。
2)設(shè)計層面不同,抽象類作為很多子類的父類,它是一種模板式設(shè)計。而接口是一種行為規(guī)范,它是一種輻射式設(shè)計。什么是模板式設(shè)計?最簡單例子,大家都用過ppt里面的模板,如果用模板A設(shè)計了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它們的公共部分需要改動,則只需要改動模板A就可以了,不需要重新對ppt B和ppt C進行改動。而輻射式設(shè)計,比如某個電梯都裝了某種報警器,一旦要更新報警器,就必須全部更新。也就是說對于抽象類,如果需要添加新的方法,可以直接在抽象類中添加具體的實現(xiàn),子類可以不進行變更;而對于接口則不行,如果接口進行了變更,則所有實現(xiàn)這個接口的類都必須進行相應(yīng)的改動。
下面看一個網(wǎng)上流傳最廣泛的例子:門和警報的例子:門都有open( )和close( )兩個動作,此時我們可以定義通過抽象類和接口來定義這個抽象概念:
abstract class Door {public abstract void open();public abstract void close(); }或者:
interface Door {public abstract void open();public abstract void close(); }但是現(xiàn)在如果我們需要門具有報警alarm( )的功能,那么該如何實現(xiàn)?下面提供兩種思路:
1)將這三個功能都放在抽象類里面,但是這樣一來所有繼承于這個抽象類的子類都具備了報警功能,但是有的門并不一定具備報警功能;
2)將這三個功能都放在接口里,需要用到報警功能的類就需要實現(xiàn)這個接口中的open( )和close( ),也許這個類根本就不具備open( )和close( )這兩個功能,比如火災(zāi)報警器。
從這里可以看出,?Door的open() 、close()和alarm()根本就屬于兩個不同范疇內(nèi)的行為,open()和close()屬于門本身固有的行為特性,而alarm()屬于延伸的附加行為。因此最好的解決辦法是單獨將報警設(shè)計為一個接口,包含alarm()行為,Door設(shè)計為單獨的一個抽象類,包含open和close兩種行為。再設(shè)計一個報警門繼承Door類和實現(xiàn)Alarm接口。
interface Alram {void alarm(); }abstract class Door {void open();void close(); }class AlarmDoor extends Door implements Alarm {void oepn() {//.... }void close() {//.... }void alarm() {//.... } }抽象類和接口在Java中的應(yīng)用
例子:假設(shè)有若干 (如1000)個Circle,Rectangle以及若干個其他形狀,希望計算它們的總面積,直截了當(dāng)?shù)淖龇ㄊ菍⑺鼈兎謩e放到多個數(shù)組中,分別循環(huán)求出各形狀的面積,然后累加,這種做法是不漂亮的。如果還有其它形狀:triangle,ellipses等,上述方法顯得“累贅”。希望有一種統(tǒng)一的表示,例如用一個數(shù)組shape[],接受所有的形狀,然后用:
for (i=0; i<shape.length; i++)area_total += shape[i].area();用抽象類實現(xiàn)多種形狀面積的累加:
首先看看Circle和Rectangle兩個類,如何完成相關(guān)參數(shù)的計算 :
class Circle {public float r; Circle(float r) {this.r = r; }public float area() {return 3.14 * r * r;} } class Rectangle {public float width, height; Rectangle (float w, float h) {width = w; height = h;}public float area() {return width * height;} }現(xiàn)在要利用抽象類實現(xiàn)多種形狀面積的累加,確保每種形狀分別用不同的方法來計算它們的面積和周長。因此,超類Shape包含抽象方法computeArea,然后在不同的子類中實現(xiàn)和覆蓋這個方法,同時添加toString方法來顯示幾何形狀的一些基本屬性。現(xiàn)在聲明了1000個Shape對象的數(shù)組,然后循環(huán)1000次隨機產(chǎn)生1000個平面圖形對象,形狀為圓、矩形、正方形三種之一。
abstract class Shape {abstract float computeArea(); } class Circle extends Shape {public float r;public Circle(float r) {this.r = r;}public float computeArea() {return (float)3.14 * r * r;} } class Rectangle extends Shape {public float width, height; Rectangle (float w, float h) {width = w; //這里不需"this"height = h;}public float computeArea() {return width * height;} }用接口實現(xiàn)多種形狀面積的累加:
用接口的方式實現(xiàn)多種形狀面積的累加,需要將用抽象類表示的Shape類改成接口。由于接口的語法定義要求,我們要把原來抽象類中的成員變量去掉,成員方法改成抽象方法computeArea(),該方法返回一個double類型。所以,這個接口定義為:
public interface Shape2 { public abstract double computeArea(); }接口實現(xiàn)如下:
interface Shape2 { public double computeArea(); } class Circle2 implements Shape2 {protected double radius;public Circle2(double _radius) {radius = _radius;}public double computeArea() { return Math.PI * radius * radius; } } class Rect2 implements Shape2 { protected double width, height;public Rect2(double w, double h) { width = w;height = h;}public double computeArea() { return width * height; } }用一個object數(shù)組實現(xiàn)多種形狀面積的累加:
定義一個數(shù)組,它可以同時存儲矩形、圓和正方形,每個Java類都是由Object擴展而來的。因此,所有的類都屬于Object類型,我們可以創(chuàng)建一個Object類型的數(shù)組來存儲任何類型的對象,也就可以存儲矩形、圓和正方形對象
完整代碼如下:
package javatest; import java.util.*; import java.io.*;interface Shape2 { public double computeArea(); } class Circle2 implements Shape2 {protected double radius;public Circle2(double _radius) {radius = _radius;}public double computeArea() { return Math.PI * radius * radius; } } class Rect2 implements Shape2 { protected double width, height;public Rect2(double w, double h) { width = w;height = h;}public double computeArea() { return width * height; } } public class javatest { public static void main(String args[ ]) { Shape2 s[] = { new Circle2(4), new Rect2(4, 4), new Circle2(10), new Rect2(20, 2), new Rect2(8, 10)};double total = 0;for(int i = 0; i < s.length; i++)total = total + s[i].computeArea();System.out.println("totalArea = " + (int)total);} }參考資料
《java接口講義》--siyuan學(xué)院
《java課程講義》--東華大學(xué)計算機學(xué)院
http://www.cnblogs.com/dolphin0520/p/3811437.html#top
作者:wuyudong 出處:http://www.cnblogs.com/wuyudong/總結(jié)
以上是生活随笔為你收集整理的java学习笔记8--接口总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java学习笔记7--抽象类与抽象方法
- 下一篇: java学习笔记9--内部类总结