国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

java類、抽象類、接口、繼承和對象解析

2019-11-17 04:03:19
字體:
來源:轉載
供稿:網友
這不是什么教材,筆者有時會在論壇上瞧瞧,看到不少初學者問到很多問題,這些問題是java程序員應該懂得的,而一般書上不會講到或者一筆帶過的知識。因此斗膽涂鴉一篇文章,把想說的在這里一口氣說完。這也是本人第一次寫技術性的文章,文筆不暢之外,還請各位見諒。


首先講清楚類和對象的區別。


類是廣泛的概念,表示一個有共同性質的群體,而對象指的是具體的一個實實在在的東西。例如,“人”是一個類,它可以表示地球上所有的人;而“張三”、“李四”、“愛因斯坦”等則是一個個的對象,或者說它們是“人”這個類的一個個實例。在 Java 中,我們可以定義類,然后創建類的對象。


例如:
// 聲明一個類“Human”
class Human{
PRivate String name;
public String getName(){
return name;
}
public void setName(String value){
this.name = value;
}
//......
}


創建一個類:
Human human = new Human();





其次,很多人對對象和對象的引用認識模糊
引用是程序操作對象的句柄,相當于C和C++中的指針。
前面說了,對象是一個實實在在的東西,比如前面的代碼:
Human human = new Human();
程序執行到這里之后,java虛擬機將會在內存中創建一個 Human 對象,并將這個對象的引用賦給 human 變量。這里有兩步,首先是創建 Human 對象,然后把創建的對象的引用賦給 human 變量。
如果聲明了一個對象的引用,但沒有將對象賦值給它,則這個引用指向了空的對象,或者說引用了不存在的對象。這時如果想通過這個引用訪問對象,則會拋出空指針異常,例如:
Human human;
//......
human.setName("張三");





下面重點談一談類、抽象類、接口和繼承之間的關系
不少細心的初學者在論壇上問類似這樣的問題:
1、接口不實現方法,但我卻在程序中可以調用接口的方法,這是為什么?比如 java.sql 包中的 Connection、Statement、ResultSet 等都是接口,怎么可以調用 它們的方法呢?
2、抽象類不能實例化,但是jdk中卻有很多抽象類的對象,這是為什么?比如 System.in 是一個 InputStream 類型對象,但 InputStream 是抽象類,怎么可以得到它的對象呢?


不管怎么樣,大家應該明白一點:不管是抽象類中的抽象方法,還是接口中定義的方法,都是需要被調用的,否則這些方法定義出來就沒有意義了。


可能有很多書上沒有提到,或者提到了而讀者沒有注意到這一點:
一個子類如果繼承了它的基類,則表示這個類也是其基類的一種類型,這個子類的一個對象是子類類型,并且同時也是其基類的一個對象,它也具有基其類的類型;一個類如果實現了一個接口,則表示這個類的一個對象也是這個接口的一個對象。


可能這樣說不太好懂,又是子類、基類、類型、接口什么的,容易搞混。其實舉個現實的例子你就會覺得其實很簡單:
如果“人”是一個基類,則“男人”是“人”的一個子類。如果“張三”是一個“男人”,也就是說“張三”是“男人”的一個對象,那么顯然“張三”也是“人”這個基類的一個對象。


明白了這一點,就容易理解為什么我們可以得到抽象類的對象了:原來我們得到的抽象類的對象其實是它的已經實現了抽象方法的子類或子孫類的一個對象,但我們拿它當它的抽象類的基類來用。比如“人”這個類,每個人都會“悲傷”,男人悲傷的時候抽煙、喝酒,女人悲傷的時候哭泣、流淚。由于不同的子類在“悲傷”時所進行的動作不一樣,因此這個動作(方法)在基類中不好實現,但基類中又需要有這個方法,因此,“人”這個類就可以定義一個抽象方法“悲傷”,由其子類“男人”和“女人”來實現“悲傷”這個方法。但是調用者只把男人和女人的對象當作其基類“人”的一個對象,調用它的“悲傷”方法。
讀者可以去體驗一下 jdk 的抽象類 java.lang.Process :
Runtime runtime = Rumtime.getRuntime();
Process process = rumtime.exec("notepad.exe");
Class cls = process.getClass();
System.out.println(cls.getName());
這時會打印出 process 類的名字,如果在 Windows 下它會是一個類似于 *Win32* 的名字,它是 Process 的一個子類。因為 process 類用于管理打開的進程,而在不同的操作系統上都有不同的實現,因此它把方法定義為 Process 的抽象方法,而具體的操作只能由對應在不同操作系統下的子實現。


下面來談接口,我們知道接口只定義了一些方法,而沒有實現這些方法。而其實,接口是一個規范,它規定了實現這個接口所要做的事情,或者說規定了實現接口的類必須具備的能力(也就是方法)。
那么我們可以這樣對比:
某種類型的駕駛執照,規定了拿到這個駕照的人必須能夠“開小汽車”和“開公共汽車”。那么我們認為這個駕照是一個接口,它規定了實現它的類所必須有的能力。
我們可以定義一個類 Driver,繼承自 Human,然后實現“駕照持有者”這個接口:
public interface DriverHolder{
public void driverCar();
public void driverBus();
}
public class Driver extends Human implements DriverHolder{
public void driverCar(){
// ......
}
public void driverBus(){
// ......
}
}


這樣一來,一個“Driver”對象,它同時也是一個 DrivreHolder 對象。即一個司機(Driver)同時是一個駕照執持有者對象。在程序中我們可以這樣:
DriverHolder driverholder = new Driver();
driverholder.driverCar();


這樣我們就解釋了為什么“接口沒有實現方法,卻可以得到接口類的對象”的問題。


但是這樣一來,肯定有人會問:為什么要定義一個接口呢,為什么不直接把這個方法定義到 Driver 類中去,然后 Driver driver = new Driver(); 一樣可以調用它的 driverCar(); 和 driverBus() 方法,這樣做豈不是方便得多?


這是因為java是單繼承的,它只能繼承于一個類,這樣它的類型就只限于其基類或者基類的基類。但是java可以實現多個接口,這樣它就可以有很多個接口的類型。就象一個人,它繼承自“脊椎動物”這個類,而“脊椎動物”又繼承自“動物”這個類,因此“張三”是個人,他是一個“脊椎動物”,當然他也是一個“動物”。但他可以繼承很多個接口,比如拿駕駛執照之后,他就是“駕照持有者”類型,他也可以拿英語六級證書,這樣他就是一個六級證書持有者等等。


明白這一點之后,我們來看一看 java 的事件機制。
java.awt.Button 類有一個 addActionListener(ActionListener l);方法。這個方法傳入的是一個接口類型:ActionListerner,在實際中,我們需要實現 ActionListener 接口,并且把實現這個接口的類的對象引用作為參數傳入。這樣,Button對象就得到了一個 ActionListener 對象,它知道這個 ActionListener 對象有一個 actionPerformed 方法,或者說它有處理 Action 事件的能力,當 Action 事件發生時,它就可以調用這個對象的 actionPerformed 方法。


比如一般我們會這樣做:
public class TestButton extends Frame implements ActionListener{
private Button btn1 = new Button();
//......

public TestButton(){
btn.addActionListener(this);
this.add(btn);
}

public void actionPerformed(ActionEvent e){

}
}


現在我們假設 ActionListener 不是接口,而是一個類。那么我們只能繼承 ActionListener 類,并且重寫 actionPerformed 方法。但是java是單繼承的,如果類繼承了 ActionListener 類,那么它就不能繼承其它的類(Frame 類)了,而不從 Frame 類繼承的話,又怎么創建窗體,怎么把 Button 放到窗體中去呢?


其實接口不完全是為了解決 java 的單繼承問題,它在某種程度上可以達到調用和實現細節的分離。
比如說,中國的民用電規范是一個接口:平均電壓220V、50Hz、Sin 交流電,水力發電廠、火力發電廠、核電廠,還有小型的柴油發電機如果按這個規范發電,則表示它們實現了這個民用電源的接口;冰箱、電視、洗衣機等家用電器使用這些電源,表示它們在調用這個接口。在這里,家用電器不管電從哪里來,只要它符合民用電源的規范就好,電源也不管它發的電用于什么工作,只管提供電源。


再回過頭來看看 Button 的事件機制。要知道,Button 要保證所有的 action 事件發生時,程序員都可以在他的代碼中處理它,圖書館管理系統、收銀系統、進銷存等等等等等等。而接口就可以做到這一點:找一個類實現 ActionListener 接口,并且讓 Button 得到這個類的對象的引用( 調用 addActionListener 方法),從而當Action事件發生時,button 創建一個包含了事件信息的對象(ActionEvent),然后調用這個接口對象的方法,到底怎么處理這次事件,這就是實現接口的類的事情了。在這里,Button 絲毫不了解 actionPerformed 方法中到底干了什么事情,也不應該知道。Button 與具體的業務邏輯完全分離開了,它可以應用到所有的場合。 
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 巴楚县| 锦屏县| 嘉禾县| 广水市| 长春市| 和林格尔县| 烟台市| 稻城县| 遂昌县| 尖扎县| 普洱| 黎平县| 沙雅县| 深圳市| 济阳县| 神木县| 宁国市| 四子王旗| 闽侯县| 浦江县| 长乐市| 九江县| 修武县| 东安县| 玉林市| 元谋县| 镇江市| 平远县| 福泉市| 青河县| 明星| 远安县| 古蔺县| 乌拉特中旗| 深泽县| 杂多县| 三穗县| 濮阳市| 河西区| 江源县| 阳原县|