例如: // 聲明一個類“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("張三");
明白了這一點,就容易理解為什么我們可以得到抽象類的對象了:原來我們得到的抽象類的對象其實是它的已經實現了抽象方法的子類或子孫類的一個對象,但我們拿它當它的抽象類的基類來用。比如“人”這個類,每個人都會“悲傷”,男人悲傷的時候抽煙、喝酒,女人悲傷的時候哭泣、流淚。由于不同的子類在“悲傷”時所進行的動作不一樣,因此這個動作(方法)在基類中不好實現,但基類中又需要有這個方法,因此,“人”這個類就可以定義一個抽象方法“悲傷”,由其子類“男人”和“女人”來實現“悲傷”這個方法。但是調用者只把男人和女人的對象當作其基類“人”的一個對象,調用它的“悲傷”方法。 讀者可以去體驗一下 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();