1. 程式人生 > >【Java面試題】抽象類是否可繼承實體類

【Java面試題】抽象類是否可繼承實體類

一道java 常見面試題,網上找到的幾乎每個 java 面試筆試題大全或集錦裡都能找到這道題。

題目如下:

問: 抽象類是否可繼承實體類 (concrete class)

答: 抽象類是可以繼承實體類,但前提是實體類必須有明確的建構函式

答案很明確,可以繼承。其實從Object就是個實體類,java的API文件裡,每個抽象類的條目裡都明確寫著直接或間接繼承自Object,所以這點是沒有疑問的。

關鍵在於這答案裡所說的“前提是實體類必須有明確的建構函式”一句,是什麼意思。

一般學習者會寫的簡單試驗程式碼:

class A{}

abstract class B extends A{}

結果完全正常,編譯通過。似乎和“實體類必須有明確的建構函式”完全沒有關係。

這個問題涉及到兩個個基礎知識:

1.

所有的class都必須有一個構造方法,如果你沒有在程式碼裡宣告構造方法,系統會自動給你生成一個公有無參的構造方法。而只要你自己聲明瞭一個構造方法,無論有參無參,私有公有,系統就不再幫你生成預設無參構造器了。

2.

所有的子類構造器都要求在第一行程式碼中呼叫父類構造器,如果不寫,系統預設去呼叫父類的無參構造器。

所以,如果把系統預設配給的方法也算進去,class A{}的程式碼實際上是

class A{

public A(){}

}

B繼承 A 的時候,則是

abstract class B extends A{

public B(){

super();

}

}

要試驗出這繼承規則的內部情況,也很簡單,在最上面那個簡單試驗程式碼裡,加上個私有構造器,有參無參都行。

class A{

private A(){}

}

這個時候,如基礎知識(1) 中所說,系統不再給你預設無參構造器, B的構造器根據(2)中的規則去呼叫super(),卻找不到A的無參構造器,所以導致abstract class B extends A{} 編譯不能通過。(因為A中沒有任何構造器可供子類呼叫,其實這個時候A只能夠供內部類繼承,我用的Eclipse的3.4版本會建議給B改名,但是這解決不了這個問題。)

現在,你應該瞭解了資料給的那句語焉不詳的“實體類必須有明確的建構函式”的含義:

1.沒寫構造器的,那是擁有預設無參公有建構函式的,子類可以什麼都不寫,讓預設構造器去呼叫它。這是最初那兩行程式碼的情況。

2.寫了子類可訪問的無參構造器的,也是一樣,子類裡可以什麼都不寫,用預設機制呼叫。

3.寫了 有參構造器卻沒寫無參構造器的,父類裡沒有子類可訪問的無參構造器,子類必須在子類構造器裡的第一句寫明,呼叫父類有參構造器,並把引數傳進去。

4.宣告為final的以及所有構造器都不在子類訪問許可權之內的類無法繼承

其實只要是在類的繼承中,無論抽象還是實體,都需要符合這個規則的。在這個繼承試驗中隨時刪掉或是加上abstract的字首,結果都沒有變化。個人覺得“實體類必須有明確的建構函式”一句實在是無法把這個情況表達清楚,所以廣大求職者還是寫得清楚些好。

我喜歡的寫法是“可以繼承,但是和實體類的繼承一樣,也要求父類可繼承,並且擁有子類可訪問到的構造器。”

 額,我筆試的時候只答的“可以繼承”。心想所有的類都從Object類繼承吧,掉了後半句。