abstract class和interface有什麼區別?_面試題:Java抽象類與介面的區別
技術標籤:abstract class和interface有什麼區別?
點選上方“程式設計師面試圈”,選擇“置頂或者星標”
與你一起成長~
公眾號回覆[資源]領取888G學習資源
很多常見的面試題都會出諸如抽象類和介面有什麼區別,什麼情況下會使用抽象類和什麼情況你會使用介面這樣的問題。本文我們將仔細討論這些話題。 抽象類與介面是java語言中對抽象概念進行定義的兩種機制,正是由於他們的存在才賦予java強大的面向物件的能力。 在討論它們之間的不同點之前,我們先看看抽象類、介面各自的特性。
抽象類
我們都知道在面向物件的領域一切都是物件,同時所有的物件都是通過類來描述的,但是並不是所有的類都是來描述物件的。如果一個類沒有足夠的資訊來描述一個具體的物件,而需要其他具體的類來支撐它,那麼這樣的類我們稱它為抽象類。比如new Animal(),我們都知道這個是產生一個動物Animal物件,但是這個Animal具體長成什麼樣子我們並不知道,它沒有一個具體動物的概念,所以他就是一個抽象類,需要一個具體的動物,如狗、貓來對它進行特定的描述,我們才知道它長成啥樣。
在面向物件領域由於抽象的概念在問題領域沒有對應的具體概念,所以用以表徵抽象概念的抽象類是不能例項化的。
抽象類是用來捕捉子類的通用特性的 。它不能被例項化,只能被用作子類的超類。抽象類是被用來建立繼承層級裡子類的模板。以JDK中的GenericServlet為例:
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
// abstract method
abstract void service(ServletRequest req, ServletResponse res);
void init() {
// Its implementation
}
// other method related to Servlet
}
當HttpServlet類繼承GenericServlet時,它提供了service方法的實現:
public class HttpServlet extends GenericServlet {
void service(ServletRequest req, ServletResponse res) {
// implementation
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
// Implementation
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
// Implementation
}
// some other methods related to HttpServlet
}
建立抽象類和抽象方法非常有用,因為他們可以使類的抽象性明確起來,並告訴使用者和編譯器打算怎樣使用他們.抽象類還是有用的重構器,因為它們使我們可以很容易地將公共方法沿著繼承層次結構向上移動。
在使用抽象類時需要注意幾點:
1、抽象類不能被例項化,例項化的工作應該交由它的子類來完成,它只需要有一個引用即可。
2、抽象方法必須由子類來進行重寫。
3、只要包含一個抽象方法的抽象類,該方法必須要定義成抽象類,不管是否還包含有其他方法。
4、抽象類中可以包含具體的方法,當然也可以不包含抽象方法。
5、子類中的抽象方法不能與父類的抽象方法同名。
6、abstract不能與final並列修飾同一個類。
7、abstract 不能與private、static、final或native並列修飾同一個方法。
介面
介面是抽象方法的集合。如果一個類實現了某個介面,那麼它就繼承了這個介面的抽象方法。這就像契約模式,如果實現了這個介面,那麼就必須確保使用這些方法。介面只是一種形式,介面自身不能做任何事情。以Externalizable介面為例:
public interface Externalizable extends Serializable {
void writeExternal(ObjectOutput out) throws IOException;
void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
當你實現這個介面時,你就需要實現上面的兩個方法:
public class Employee implements Externalizable {
int employeeId;
String employeeName;
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
employeeId = in.readInt();
employeeName = (String) in.readObject();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(employeeId);
out.writeObject(employeeName);
}
}
在使用介面過程中需要注意如下幾個問題:
1、個Interface的方所有法訪問許可權自動被宣告為public。確切的說只能為public,當然你可以顯示的宣告為protected、private,但是編譯會出錯!
2、介面中可以定義“成員變數”,或者說是不可變的常量,因為介面中的“成員變數”會自動變為為public static final。可以通過類命名直接訪問:ImplementClass.name。
3、介面中不存在實現的方法。
4、實現介面的非抽象類必須要實現該介面的所有方法。抽象類可以不用實現。
5、不能使用new操作符例項化一個介面,但可以宣告一個介面變數,該變數必須引用(refer to)一個實現該介面的類的物件。可以使用 instanceof 檢查一個物件是否實現了某個特定的介面。例如:if(anObject instanceof Comparable){}。
6、在實現多介面的時候一定要避免方法名的重複。
二者區別
引數 | 抽象類 | 介面 |
---|---|---|
預設的方法實現 | 它可以有預設的方法實現 | 介面完全是抽象的。它根本不存在方法的實現 |
實現 | 子類使用extends關鍵字來繼承抽象類。如果子類不是抽象類的話,它需要提供抽象類中所有宣告的方法的實現。 | 子類使用關鍵字implements來實現介面。它需要提供介面中所有宣告的方法的實現 |
構造器 | 抽象類可以有構造器 | 介面不能有構造器 |
與正常Java類的區別 | 除了你不能例項化抽象類之外,它和普通Java類沒有任何區別 | 介面是完全不同的型別 |
訪問修飾符 | 抽象方法可以有public、protected和default這些修飾符 | 介面方法預設修飾符是public。你不可以使用其它修飾符。 |
main方法 | 抽象方法可以有main方法並且我們可以執行它 | 介面沒有main方法,因此我們不能執行它。 |
多繼承 | 抽象方法可以繼承一個類和實現多個介面 | 介面只可以繼承一個或多個其它介面 |
速度 | 它比介面速度要快 | 介面是稍微有點慢的,因為它需要時間去尋找在類中實現的方法。 |
新增新方法 | 如果你往抽象類中新增新的方法,你可以給它提供預設的實現。因此你不需要改變你現在的程式碼。 | 如果你往介面中新增方法,那麼你必須改變實現該介面的類。 |
總結
1、 抽象類在java語言中所表示的是一種繼承關係,一個子類只能存在一個父類,但是可以存在多個介面。
2、 在抽象類中可以擁有自己的成員變數和非抽象類方法,但是介面中只能存在靜態的不可變的成員資料(不過一般都不在介面中定義成員資料),而且它的所有方法都是抽象的。
3、抽象類和介面所反映的設計理念是不同的,抽象類所代表的是“is-a”的關係,而介面所代表的是“like-a”的關係。
抽象類和介面是java語言中兩種不同的抽象概念,他們的存在對多型提供了非常好的支援,雖然他們之間存在很大的相似性。但是對於他們的選擇往往反應了您對問題域的理解。只有對問題域的本質有良好的理解,才能做出正確、合理的設計。
參考資料
https://blog.csdn.net/chenssy/article/details/12858267
http://www.importnew.com/12399.html
-end-
用心分享面試知識,做有溫度的攻城獅
每天記得對自己說:你是最棒的!
往期推薦:
888G面試資源分享
面試題:Java面向物件的特徵
面試題:請你說說“面向物件六大原則”?
面試題:談談final、finally、finalize的區別
每一個“好看”,都是對我們最大的肯定!