Java中比較抽象類與接口的異同
一.抽象類
(一)概念
? ? ? 在繼承的層次結(jié)構(gòu)中,每個(gè)新的子類都使類變得更加明確和具體。如果從一個(gè)子類向父類追溯,類就會(huì)變得更通用、更加不明確。類的設(shè)計(jì)應(yīng)該確保父類包含它的子類的共同特征。有時(shí)候,一個(gè)父類設(shè)計(jì)得非常抽象,以至于它都沒(méi)有任何具體的實(shí)例。這樣的類稱為抽象類(abstract class)。在類的頭部使用?abstract?修飾符表示該類為抽象類。
(二)抽象類和抽象方法
? ? ? ?同樣用?abstract?聲明抽象方法。抽象方法(abstract method)只定義成員方法的接口形式,而沒(méi)有具體操作。只有派生類對(duì)抽象成員方法的重定義才能真正實(shí)現(xiàn)與該派生類相關(guān)的操作。在各子類繼承了父類的抽象方法之后,再分別用不同的語(yǔ)句和方法體來(lái)重新定義它,形成若干個(gè)名字相同、返回值相同、參數(shù)列表相同、目的一致但是具體實(shí)現(xiàn)有一定差別的方法。抽象類中定義抽象方法的目的是實(shí)現(xiàn)一個(gè)接口,即所有的子類對(duì)外都呈現(xiàn)一個(gè)相同名字的方法。
1.一個(gè)包含抽象方法的類必須聲明為抽象類
? ? 幾點(diǎn)說(shuō)明:
? ?1.抽象類不一定有抽象方法,但有抽象方法的類一定是抽象類。
? ?2.即使子類的父類是具體的,這個(gè)子類也可以是抽象的。
? ?3.當(dāng)父類的方法實(shí)現(xiàn)在子類中變得無(wú)效時(shí),子類可以重寫(xiě)父類的方法并將它定義為抽象的。
2.抽象方法只有定義而沒(méi)有實(shí)現(xiàn),它的實(shí)現(xiàn)由子類提供
? 下面定義了一個(gè)抽象類Object類:
public abstract class Object {
public abstract double getArea();
public abstract double getPerimeter();
}
Object類是多個(gè)子類的父類,由于在多個(gè)子類中都要用到getArea()方法和getPermeter()方法,所以在父類中定義比較好;由于計(jì)算面積和周長(zhǎng)的getArea()方法和getPermeter()方法在不同子類里的實(shí)現(xiàn)方式不同,所以O(shè)bject類中定義的這兩個(gè)方法的實(shí)現(xiàn)只能由子類提供。
3.抽象類無(wú)法被直接實(shí)例化,可以讓子類繼承然后實(shí)例化子類
? 通過(guò)一個(gè)例子來(lái)說(shuō)明:
public abstract class Person {
//定義一個(gè)抽象方法
public abstract void isSmoke();
}
//學(xué)生類
class Students extends Person{
//繼承抽象類后抽象類中的抽象方法必須在子類中實(shí)現(xiàn)
public void isSmoke() {
System.out.print("Students can't smoke.");
}
}
//教師類
class Teachers extends Person{
public void isSmoke() {
System.out.print("Teachers can smoke.");
}
}
(三)使用抽象類的意義
? ? ? ?因?yàn)槌橄箢惒荒軐?shí)例化對(duì)象,必須要有子類來(lái)實(shí)現(xiàn)它之后才能使用。這樣就可以把一些具有相同屬性和方法的組件進(jìn)行抽象,更有利于代碼和程序的維護(hù)。同時(shí),抽象類也是Java面向?qū)ο蟮囊粋€(gè)重要體現(xiàn)。
二.接口
(一)概念
? ? ? ? ?接口(Interface),在Java編程語(yǔ)言中是一個(gè)抽象類型,是象方法的集合。
? ? ? ? ?接口通常以? ?interface??來(lái)聲明。一個(gè)類通過(guò)繼承接口的方式,從而來(lái)繼承接口的抽象方法。
? ? 接口有以下特性:
接口是隱式抽象的,當(dāng)聲明一個(gè)接口的時(shí)候,不必使用abstract關(guān)鍵字。接口中每一個(gè)方法也是隱式抽象的,聲明時(shí)同樣不需要abstract關(guān)鍵字。接口中的方法都是公有的。
(二)語(yǔ)法
?1. 定義:一個(gè)簡(jiǎn)單的接口擁有全局變量和抽象方法。在接口中的所有方法都必須只聲明方法標(biāo)識(shí),而不要去聲明具體的方法體,因?yàn)榫唧w的方法體的實(shí)現(xiàn)是由繼承該接口的類來(lái)去實(shí)現(xiàn)的。
?接口定義的一般形式為:
?[訪問(wèn)控制符]interface <接口名> {
? ? ? ? ?類型標(biāo)識(shí)符final 符號(hào)常量名n = 常數(shù);
? ? ? ? ?返回值類型? 方法名([參數(shù)列表]);
? ? ? ? ?…
?}????????
? 定義接口實(shí)例:
interface Human {
//定義一個(gè)全局變量
final String txt="吸煙有害健康";
//定義一個(gè)抽象方法
public void isSmoke();
}
?2.實(shí)現(xiàn):要實(shí)現(xiàn)接口,就必須去實(shí)現(xiàn)接口規(guī)定的方法,只有把接口規(guī)定的抽象方法都給實(shí)現(xiàn)了,才承認(rèn)這個(gè)類實(shí)現(xiàn)了這個(gè)接口,實(shí)現(xiàn)了這個(gè)接口代表的某種功能。使用 implements 關(guān)鍵字實(shí)現(xiàn)接口。
? 實(shí)現(xiàn)接口實(shí)例:
class Student implements Human{
public void isSmoke() {
System.out.println("Students can't smoke.");
}
public static void main(String[] args) {
Student h=new Student();
h.isSmoke();
System.out.println(txt);
}
}
3.接口的繼承
??子接口可以對(duì)父接口的方法和常量進(jìn)行重寫(xiě)。例如:
// 接口 Student 繼承 Human
public interface Student extends Human {
// 重寫(xiě)父接口中的txt
String txt = "未成年禁止吸煙";
// 重寫(xiě)父接口中的isSmoke()方法
void isSmoke();
}
?注意: 在Java中,類的多繼承是不合法的,但接口允許多繼承。
public interface C extends A, B
三.比較抽象類與接口
Q: 為什么有了抽象類還要接口?
看起來(lái)抽象類除了多繼承以外,完全可以完成接口所作的事情,為什么還需要定義接口呢?
1、避免java單繼承的局限
2、避免多繼承帶來(lái)的復(fù)雜性和低效性
3、面向接口編程帶來(lái)的優(yōu)勢(shì)。降低程序間的耦合,易擴(kuò)展,易維護(hù)
?Q: 如何確定在什么情況下應(yīng)該使用接口,什么情況下應(yīng)該使用類呢?
? ? ? ? 抽象類和接口都是用來(lái)指定多個(gè)對(duì)象的共同特征的。那么如何確定在什么情況下應(yīng)該使用接口,什么情況下應(yīng)該使用類呢?一般來(lái)說(shuō),清晰描述父子關(guān)系的強(qiáng)的“是......的一種”關(guān)系應(yīng)該用類建模。弱的“是..的一種”關(guān)系也稱為類屬關(guān)系,它表明對(duì)象擁有某種屬性,可以用接口來(lái)建模。
類型抽象類接口定義abstract關(guān)鍵字interface關(guān)鍵字繼承可以繼承一個(gè)類和實(shí)現(xiàn)多個(gè)接口;子類只可以繼承一個(gè)抽象類接口只可以繼承接口(一或多);子類可以實(shí)現(xiàn)多個(gè)接口方法實(shí)現(xiàn)可定義構(gòu)造方法,可以有抽象方法和具體方法無(wú)構(gòu)造方法,且方法都是抽象的,也沒(méi)有方法的實(shí)現(xiàn)實(shí)現(xiàn)方式子類使用extend關(guān)鍵字來(lái)繼承抽象類。如果子類不是抽象類,需要提供抽象類中所有聲明的方法的實(shí)現(xiàn)子類使用關(guān)鍵字implements來(lái)實(shí)現(xiàn)接口。需要提供接口中所有聲明的方法的實(shí)現(xiàn)作用把相同的東西提取出來(lái),即重用把程序模塊進(jìn)行固化的契約,降低耦合
到此這篇關(guān)于Java中比較抽象類與接口的異同的文章就介紹到這了,更多相關(guān)Java抽象類與接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
idea2020導(dǎo)入spring5.1的源碼詳細(xì)教程
這篇文章主要介紹了idea2020導(dǎo)入spring5.1的源碼的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
詳解Android系統(tǒng)中的root權(quán)限獲得原理
這篇文章主要介紹了詳解Android系統(tǒng)中的Root權(quán)限獲得原理,安卓基于Linux,所以原理也相當(dāng)于Linux中的root用戶,需要的朋友可以參考下2015-08-08
輕量級(jí)聲明式的Http庫(kù)——Feign的獨(dú)立使用
這篇文章主要介紹了輕量級(jí)聲明式的Http庫(kù)——Feign的使用教程,幫助大家更好的理解和學(xué)習(xí)使用feign,感興趣的朋友可以了解下2021-04-04
MyBatis的注解使用、ORM層優(yōu)化方式(懶加載和緩存)
這篇文章主要介紹了MyBatis的注解使用、ORM層優(yōu)化方式(懶加載和緩存),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
eclipse導(dǎo)入工程報(bào)錯(cuò)問(wèn)題項(xiàng)目或者文件有紅叉的解決方案
這篇文章主要介紹了eclipse導(dǎo)入工程報(bào)錯(cuò)問(wèn)題項(xiàng)目或者文件有紅叉的解決方案,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
Java線程隊(duì)列LinkedBlockingQueue的使用
本文主要介紹了Java線程隊(duì)列LinkedBlockingQueue的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
解決Mybatis中result標(biāo)簽識(shí)別不了的情況
這篇文章主要介紹了解決Mybatis中result標(biāo)簽識(shí)別不了的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。2022-01-01
SpringCloud?OpenFeign?服務(wù)調(diào)用傳遞?token的場(chǎng)景分析
這篇文章主要介紹了SpringCloud?OpenFeign?服務(wù)調(diào)用傳遞?token的場(chǎng)景分析,本篇文章簡(jiǎn)單介紹?OpenFeign?調(diào)用傳遞?header?,以及多線程環(huán)境下可能會(huì)出現(xiàn)的問(wèn)題,其中涉及到?ThreadLocal?的相關(guān)知識(shí),需要的朋友可以參考下2022-07-07

