java繼承與接口 html
前兩天寫東西,原本想把定義和實現分開來寫的。類A有兩個方法f1和f2,想把類A的定義、f1的實現和f2的實現分爲三個java文件來寫,看了看抽象類和接口。不過貌似都不是搞這個的樣子。(求方法) java
總結一下,本身看的繼承和接口。 c++
Java中很基本的概念。如書所言: 設計模式
(1)java不支持多重繼承,也就是說子類至多隻能有一個父類 eclipse
(2)子類繼承了其父類中不是私有的成員變量和成員方法,做爲本身的成員變量和方法 函數
(3)子類中定義的成員變量和父類中定義的成員變量相同時,則父類中的成員變量不能被繼承 spa
(4)子類中定義的成員方法,而且這個成員方法的名字,返回類型,及參數個數和類型與父類的某個成員方法徹底相同,則父類的成員方法不能被繼承。 .net
其實看這個,遠遠不夠啊。仍是看代碼,能跑出什麼來纔是真啊。 設計
代碼以下: code
輸出以下:
分析一下:
1 在實例化對象時, 先對給靜態變量分配內存空間並初始化,而後執行靜態塊。所以,在這裏會輸出:
static
a:a
a:a的輸出也說明是先初始化靜態變量而後再執行靜態塊,不然a將爲null。同時,若是將「"a:"+a」修改 爲「"a:"+b」,eclipse自動報錯也說明靜態變量->靜態快,再其它。
2而後在內存中爲Employee分配內存空間,並作默認初始化(即全部變量初始化爲默認值,這裏都初始化爲null)。
3 默認初始化完成後,開始顯示初始化。即執行「private String b = "b"; 將b初始化"b",而且執行非靜態方法塊;所以在這裏會有如下輸出:
no static
b:b
4 最後才調用默認構造函數,在默認構造函數中調用了帶參數的構造函數,因此在這裏先輸出帶參數構造test_java(string),此時b已經被修改成「Un」,再輸出test_java()。
能夠看出: 若是在類內有靜態變量和靜態塊,就先靜態後非靜態,最後纔是構造函數;
接下分析一下
父類:
父類是個抽象類,能夠有本身的數據成員,也能夠有非abstarct的成員方法。可是不能被實例化。
子類1:
該子類C1實現了父類全部的方法,抽象和非抽象的。
子類2:
子類C2實現了父類的抽象方法。子類在繼承抽象類時,必須實現抽象類中的全部抽象方法。
來看看下面一段代碼會有什麼樣的輸出。
先本身看看,再來對照結果:
哇,仍是有點多。咱們來仔細分析一下。
從總體上來講,咱們知道從對象的內存角度來講,假設如今有一個父類Father,它裏面的變量須要佔用1M內存.有一個它的子類Son,它裏面的變量須要佔用0.5M內存.
如今經過代碼來看看內存的分配狀況:
Father f = new Father();//系統將分配1M內存.
Son s = new Son();//系統將分配1.5M內存!由於子類中有一個隱藏的引用super會指向父類實例,因此在實例化子類以前會先實例化一個父類,也就是說會先執行父類的構造函數.因爲s中包含了父類的實例,因此s能夠調用父類的方法.
有了總體認識,來一個一個看輸出。
1、C1 c1 = new C1(0);對應輸出了A ;A 0;C1 1;先輸出A,這點同時驗證了子類先初始化父類,再執行父類構造函數A 0;再子類的構造函數C1 1.
2、C2 c2 = new C2(0);對應輸出了A 0;C2 8;看出父類初始化只有一次,當構造函數必須在執行一次。
3、子類c1實現了本身的f1、f2、f3,使用時就是使用的本身的實現;子類c2沒有實現f3,調用父類的實現。可是隻使用父類的方法,數據成員仍是本身的,全部輸出「A f3 8」。
由此,可推斷,這三個類內存結構如圖:
父類A 子類C1 子類C2
i |
I |
I |
F1 F2 F3 |
F1 F2 F3 |
F1 F2 F3 |
|
F1 F2 F3 |
F1 F2 |
如今在回去看看開頭出的四點,確實是那樣,而且後面對凌亂的代碼驗證有更好的認識。下面講講繼承中的一些其它內容。
super關鍵字在java中的做用是使被屏蔽的成員變量或者成員方法或變爲可見,或者說用來引用被屏蔽的成員變量和成員成員方法。super是用在子類中,目的是訪問直接父類中被屏蔽的成員。
Father f = new Father();//系統將分配1M內存.
Son s = new Son();//系統將分配1.5M內存!由於子類中有一個隱藏的引用super會指向父類實例,因此在實例化子類以前會先實例化一個父類,也就是說會先執行父類的構造函數.因爲s中包含了父類的實例,因此s能夠調用父類的方法.
Son s1 = s;//s1指向那1.5M的內存.
Father f1 = (Father)s;//這時f1會指向那1.5M內存中的1M內存,便是說,f1只是指向了s中實例的父類實例對象,因此f1只能調用父類的方法(存儲在1M內存中),而不能調用子類的方法(存儲在0.5M內存中).
Son s2 = (Son)f;//這句代碼運行時會報ClassCastException.由於f中只有1M內存,而子類的引用都必需要有1.5M的內存,因此沒法轉換.
Son s3 = (Son)f1;//這句能夠經過運行,這時s3指向那1.5M的內存.因爲f1是由s轉換過來的,因此它是有1.5M的內存的,只是它指向的只有1M內存.
Java語言不支持一個類有多個直接的父類(多繼承),但能夠實現(implements)多個接口,間接的實現了多繼承.
接口使用有幾點須要注意的:
1、Java接口與c++的純虛基類相似。成員變量默認都是public,static,final類型的(均可省略),必須被顯示初始化,即接口中的成員變量爲常量(大寫,單詞之間用"_"分隔)
2, Java接口中的方法默認都是public,abstract類型的(均可省略),沒有方法體,不能被實例化
下面都是不對的。
public interface A{
int var; //錯,var是常量,必須顯示初始化
void method(){...}; //錯,接口中只能包含抽象方法
protected void method2(); //錯,接口中的方法必須是public類型
static void method3(){...}; //錯,接口中不能包含靜態方法
}
我我的覺得,接口就是一個純抽象類,只有抽象方法,堅定不能有實現。實現接口便是在給本身的類添加一個或多個方法。使用接口是爲了在設計模式上的規範。
這個我仍是推薦看看http://www.blogjava.net/chunkyo/archive/2007/01/21/95093.html。講的很是好,只是不知道原創是誰。