Java中的抽象類、接口、設計模式、包裝類和泛型(附帶相關面試題)

?一.抽象類(abstract)
abstract class className{ }
1.抽象類就是一個一些事務的具體抽象,比如說狗,貓,兔子等等可以往上抽象成同一個概念,即是動物的這個抽象類,因為都有著差不多的行為邏輯,所以抽象類中可以有吃,睡等共同方法
2.由于抽象類無法直接進行實例化,所以需要通過實例化子類實現(xiàn)向上轉型,但是如果抽象類中有著static方法,則可以直接調(diào)用其方法而不需要實例化
3.必須有子類繼承抽象類,而final類沒有子類,所以抽象類不能是final類
4.抽象類中有多種方法可以使用,有普通方法,static方法,還有抽象方法
5.子類繼承抽象類時候必須實現(xiàn)父類中的抽象方法
6.子類繼承抽象類只能繼承一個即所謂的單繼承限制
7.如果抽象類中有構造函數(shù)則需要子類在繼承的時候通過super()函數(shù)
案例代碼:創(chuàng)建一個萬物動物類與多個具體動物類

*面試題: 普通類和抽象類有哪些區(qū)別?
抽象類不能被實例化;
抽象類可以有抽象方法,只需申明,無須實現(xiàn);
有抽象方法的類一定是抽象類;
抽象類的子類必須實現(xiàn)抽象類中的所有抽象方法,否則子類仍然是抽象類;
抽象方法不能聲明為靜態(tài)、不能被static、final修飾。(注意是抽象方法,普通方法沒限制)

二.接口(interface)
interface interfaceName { }
接口的抽象要大于抽象類,因為接口可以繼承接口,所以在分類向下劃分的時候通常都使用接口,比如動物可以分為哺乳動物,卵生動物。而哺乳動物又分為大型動物,小型動物,再細分其具體動物。如果用抽象類會受到單繼承限制。無法一步步細分,所以在能夠同時使用接口和抽象類的前提下盡量使用接口
1.接口需要有子類繼承(實現(xiàn))接口
2.接口中方法有 抽象方法 后來的 default的普通方法 和 static方法
3.接口相比于抽象類,子類可以繼承(實現(xiàn))多個接口
案例代碼:創(chuàng)建動物接口

*面試題: 接口和抽象類有什么區(qū)別?
(1)接口
接口使用interface修飾;
接口不能實例化;
類可以實現(xiàn)多個接口;①java8之前,接口中的方法都是抽象方法,省略了public abstract。②java8之后;接口中可以定義靜態(tài)方法,靜態(tài)方法必須有方法體,普通方法沒有方法體,需要被實現(xiàn);
(2)抽象類
抽象類使用abstract修飾;
抽象類不能被實例化;
抽象類只能單繼承;
抽象類中可以包含抽象方法和非抽象方法,非抽象方法需要有方法體;
如果一個類繼承了抽象類,①如果實現(xiàn)了所有的抽象方法,子類可以不是抽象類;②如果沒有實現(xiàn)所有的抽象方法,子類仍然是抽象類。

三.設計模式
抽象類的模板模式 接口的工廠設計模式和代理模式
抽象類:模板模式
抽象類的模板模式(Template Pattern): 模板模式是一種行為設計模式,它通過定義一個抽象類作為模板,其中包含一個算法的骨架,將一些方法的實現(xiàn)推遲到具體子類中。這使得子類可以在不改變算法結構的情況下重寫特定的步驟。抽象類充當模板的角色,定義了整個算法的流程和順序,而具體子類提供特定步驟的實現(xiàn)。
?案例代碼: 煮茶和泡咖啡就是一個比較典型的例子,完成喝咖啡或者茶的動作就只有加入茶葉和咖啡不同其他的行為就都一樣,一樣的喝東西行為就是一個模板。

接口:工廠設計模式 代理設計模式
1.工廠設計模式
接口的工廠設計模式(Factory Design Pattern): 工廠設計模式是一種創(chuàng)建型設計模式,用于創(chuàng)建對象的過程被封裝在一個共同的接口中。它通過定義一個工廠接口和多個具體的工廠類來實現(xiàn)對象的創(chuàng)建,由客戶端通過工廠接口來請求對象的創(chuàng)建,而不需要關心具體的實現(xiàn)類。接口定義了創(chuàng)建對象的標準和方法,而具體的工廠類負責實現(xiàn)對象的創(chuàng)建邏輯。
案例:一個比較典型的汽車工廠CarFactory 里面有SuvCar,Bus,我可以自己通過輸入字符串比如Bus就能自動創(chuàng)建相應的對象

?2.代理模式:
接口的代理模式(Proxy Pattern): 代理模式是一種結構型設計模式,它提供了一個代理類來控制對另一個對象的訪問。代理類和原始對象實現(xiàn)了同樣的接口,客戶端通過代理類來訪問原始對象,并且可以在代理類中添加額外的功能,如權限驗證、緩存等。接口定義了客戶端與代理類和原始對象之間的交互方式,而代理類充當了對原始對象的訪問控制和附加功能的提供者。
案例:代理類內(nèi)部會將所有對象實例化,所以主類只要實例化代理類就等于把所有的類對象都實例化過一遍,只需要調(diào)用自己想要的代理方法就行。核心就在于主類是通過代理類間接訪問對象

四.包裝類
1.功能
1.大家熟悉String是作為一個類,而并非數(shù)據(jù)類型,所以為了將int double float boolean等等這些基本的數(shù)據(jù)類型也轉為一個類,就是所謂包裝,每個數(shù)據(jù)類型對應的類分別是 int ->Integer類double->Double類 boolean->Boolean類
2.數(shù)據(jù)轉換
核心的幾個函數(shù)
Integer.parseInt(String s)
:將字符串參數(shù)解析為帶符號的十進制整數(shù)。如果字符串無效或格式不正確,將拋出NumberFormatException
異常。返回解析后的整數(shù)值。Double.parseDouble(String s)
:將字符串參數(shù)解析為一個雙精度浮點數(shù)。如果字符串無效或格式不正確,將拋出NumberFormatException
異常。返回解析后的浮點數(shù)值。Boolean.parseBoolean(String s)
:將字符串參數(shù)解析為布爾值。如果字符串是忽略大小寫的 "true",則返回true
;否則返回false
。String.valueOf(Object obj)
:返回給定對象的字符串表示。如果對象為null
,則返回字符串 "null"。

3.Object類接受所有類型數(shù)據(jù)
1.Object類是所有類的父類,那也就意味著Object可以接受所有的數(shù)據(jù)類型,也就是說如果在不知道方法要接受什么具體類型的數(shù)據(jù)時候,那么就進行Object定義并接受對應內(nèi)容,到時候再進行強制向下轉型。

問題引出:但是強制向下轉型可能會出現(xiàn)ClassCaseException錯誤,而如果用之前的instanceOf可能會非常麻煩,因為定義的數(shù)據(jù)可能是字符串但是將其強行向下轉型到(Integer)類型則會報錯,為此就提出一個新的概念--泛型
五.泛型
泛型是為了避免出現(xiàn)ClassCaseException的異常而出現(xiàn),而該異常大概率是因為強制向下轉型而出現(xiàn)的問題,故此泛型的解決辦法就是避免出現(xiàn)向下轉型
1.泛型的格式
類需要進行標記<>
2.泛型的引用與泛型引用通配符 “?”傳遞數(shù)據(jù)的上限和下限
?1.泛型的引用:
案例代碼:
? 2.通配符 “?”傳遞數(shù)據(jù)的上限和下限以及區(qū)別:
<?extends Number>:
只能用Number類或者其子類(Integer Double Boolean)即所謂上限,父類受到限制
<?super String>:
只能用String類或者其父類Object類即所謂下線,子類受到限制
3.泛型的作用
當我們編寫代碼時,可能會遇到需要處理多種數(shù)據(jù)類型的情況。泛型就像是一種通用的工具,它可以讓我們在不同的地方使用相同的代碼來處理不同的數(shù)據(jù)類型。
舉個例子,假設我們有一個存儲整數(shù)的容器類。如果沒有泛型,我們可能需要為存儲整數(shù)、字符串、浮點數(shù)等不同類型的值分別編寫不同的容器類。這樣就會導致代碼重復,增加維護難度。
而有了泛型,我們可以編寫一個通用的容器類,在需要存儲不同類型的值時,只需要指定具體的類型,讓泛型去幫助我們處理具體的類型操作。這樣,我們就可以使用相同的代碼去處理不同的數(shù)據(jù)類型,比如添加、刪除、獲取值等操作。
在使用泛型的時候,并不能直接修改泛型類中定義的屬性。但是,我們可以通過提供方法(setter 和 getter)來操作和修改泛型類中的屬性。這樣,外部代碼可以通過調(diào)用方法來改變內(nèi)部屬性的值。
總的來說,泛型的作用就是讓我們能夠編寫通用、可復用的代碼,用于處理不同的數(shù)據(jù)類型。它簡化了代碼的編寫,提高了代碼的可讀性和可維護性。雖然不能直接修改泛型類中的屬性,但我們可以通過方法來操作和修改屬性的值。