【Java的抽象類和接口】

1. 抽象類

1.1 抽象類概念

在面向對象的概念中,所有的對象都是通過類來描繪的,但是反過來,并不是所有的類都是用來描繪對象的,如果 一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。

以上代碼中,這個方法是否可以不用實現? 這個寫了跟沒寫是一樣的

所以我們就可以不去實現他,類似c語言中的函數聲明

但是呢,這里顯示報錯了

1,一個方法可以被修飾為abstract,此時代表這個方法可以不進行實現,被稱為抽象方法!

2,如果一個類當中包含抽象方法,此時這個類必須時抽象類。若沒有抽象方法,這個類也可以被寫為抽象類。

問題:什么情況下一個類可以被定義為一個抽象類?

答:當不能具體描述一個對象的時候

3,抽象類中定義成員和普通類沒有區別

4,抽象類不能具體的描述一個對象,在main方法中就不能被實例化

????????

問題:抽象類不可以被實例化,那么存在的意義是什么?

答:為了被繼承

5,當一個普通類繼承這個抽象類之后,必須重寫抽象類當中的抽象方法!

6,抽象類也可以發生向上轉型,動態綁定,多態!

1.2 抽象類語法

在Java中,一個類如果被 abstract 修飾稱為抽象類,抽象類中被 abstract 修飾的方法稱為抽象方法,抽象方法不用給出具體的實現體。

注意:抽象類也是類,內部可以包含普通方法和屬性,甚至構造方法

1.3 抽象類特性

1. 抽象類不能直接實例化對象(上面以講過)

2,抽象方法也需要滿足重寫的特點。被static,private,final修飾都不能發生重寫的

所以abstract和final是對立的,不可能同時存在

3. 抽象類必須被繼承,并且繼承后子類要重寫父類中的抽象方法,否則子類也是抽象類,必須要使用 abstract 修飾

當一個普通類A繼承了一個抽象類,不想重寫這個抽象方法,此時,可以把這個普通類A改為抽象類。

但是,如果A這個抽象類再次被普通類B繼承,此時B這個類,需要重新所以未被重寫的抽象方法!

4. 抽象類中不一定包含抽象方法,但是有抽象方法的類一定是抽象類

5. 抽象類中可以有構造方法,供子類創建對象時,初始化父類的成員變量

1.4 抽象類的作用

抽象類本身不能被實例化, 要想使用, 只能創建該抽象類的子類. 然后讓子類重寫抽象類中的抽象方法.

使用抽象類相當于多了一重編譯器的校驗.

使用抽象類的場景就如上面的代碼, 實際工作不應該由父類完成, 而應由子類完成. 那么此時如果不小心誤用成父類了, 使用普通類編譯器是不會報錯的. 但是父類是抽象類就會在實例化的時候提示錯誤, 讓我們盡早發現問題

2. 接口

2.1 接口的概念

在現實生活中,接口的例子比比皆是,比如:筆記本上的USB口,電源插座等。

電腦的USB口上,可以插:U盤、鼠標、鍵盤...所有符合USB協議的設備

電源插座插孔上,可以插:電腦、電視機、電飯煲...所有符合規范的設備

通過上述例子可以看出:接口就是公共的行為規范標準,大家在實現時,只要符合規范標準,就可以通用。 在Java中,接口可以看成是:多個類的公共規范,是一種引用數據類型。

2.2 語法規則

接口的定義格式與定義類的格式基本相同,將class關鍵字換成 interface 關鍵字,就定義了一個接口。

創建接口:

定義接口:interface + 接口名? ? ?會生成一個字節碼文件

1,接口的定義可以使用interface定義

2,接口當中可以有方法和屬性

但是這里報錯了。接口當中的成員變量,默認為public static final修飾的,定義的時候必須初始化

以后定義的時候,可以省略掉public static final

3,接口當中方法默認是public abstract修飾的,你不寫的時候也是抽象方法,不能有具體的實現。

4,接口當中使用default修飾的方法和static修飾的方法時可以有具體實現的 {}。

?

5,接口不可以被實例化

6,接口需要被實現,此時使用關鍵詞implements來實現。

7,當一個類實現了一個接口,那么此時這個類就要重寫這個方法。

8,接口也可以發生向上轉型,也可以發生動態綁定,也可以發生多態!

提示:

1. 創建接口時, 接口的命名一般以大寫字母 I 開頭.

2. 接口的命名一般使用 "形容詞" 詞性的單詞.

3. 阿里編碼規范中約定, 接口中的方法和屬性不要加任何修飾符號, 保持代碼的簡潔性.

2.3 接口使用

接口不能直接使用,必須要有一個"實現類"來"實現"該接口,實現接口中的所有抽象方法。

1.USB接口

2,鼠標類,實現USB接口

3,鍵盤類,實現USB接口

4,電腦類:使用USB設備及測試類

5,輸出

2.4 接口特性

1. 接口類型是一種引用類型,但是不能直接new接口的對象

2. 接口中每一個方法都是public的抽象方法, 即接口中的方法會被隱式的指定為 public abstract(只能是 public abstract,其他修飾符都會報錯)

3. 接口中的方法是不能在接口中實現的,只能由實現接口的類來實現

4. 重寫接口中方法時,不能使用默認的訪問權限

5. 接口中可以含有變量,但是接口中的變量會被隱式的指定為 public static final 變量

6. 接口中不能有靜態代碼塊和構造方法

7. 接口雖然不是類,但是接口編譯完成后字節碼文件的后綴格式也是.class

8. 如果類沒有實現接口中的所有的抽象方法,則類必須設置為抽象類

9. jdk8中:接口中還可以包含default方法。

因為test3是一個默認方法,所以可以使用testDemo調用!

test2是一個靜態方法,使用接口名去調用

static,private,final修飾的方法不能被重寫

2.5 實現多個接口

在Java中,類和類之間是單繼承的,一個類只能有一個父類,即Java中不支持多繼承,但是一個類可以實現多個接口。

這個類同時具備了IA接口的行為和IB接口的行為

Java的接口解決了Java不能多繼承的問題!

注意:一個類實現多個接口時,每個接口中的抽象方法都要實現,否則類必須設置為抽象類。

繼承表達的含義是 is - a 語義, 而接口表達的含義是具有 xxx 特性

例如:魚能游泳,狗能跑,鴨子能跑能游泳還能飛

上面的代碼展示了 Java 面向對象編程中最常見的用法: 一個類繼承一個父類, 同時實現多種接口

這樣設計有什么好處呢? 時刻牢記多態的好處, 讓程序猿忘記類型. 有了接口之后, 類的使用者就不必關注具體類型, 而只關注某個類是否具備某種能力

2.6 接口間的繼承

在Java中,類和類之間是單繼承的,一個類可以實現多個接口,接口與接口之間可以多繼承。即:用接口可以達到多繼承的目的。

IC這個接口,不僅具備了自己的testC這個功能,還擴展了IA和IB的功能

接口間的繼承相當于把多個接口合并在一起.

2.7 接口使用實例

例如:比較兩個對象誰大誰小

對于引用數據類型來說,只能通過特定的方式來比較。此時就需要使用一個接口,這個接口當中的方法可以幫助我們完成任務!

我們就有一個Comparable接口來實現

此時,可以看到源碼里面有一個compareTo方法

這個方法并沒有實現,所以就要重寫這個方法!

需要我們自定義:? ? ? ? ?------>? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 優化:

此時就可以實現兩個對象的比較

對于compareTo來說不管根據什么比較,一定是指定了一種比較方式

字符串的比較也可根據compareTo來比較

再寫一個例子:給對象數組排序

現在就是一個普通的代碼

我們發現在運行是報錯了。

在這里他并不知道要對誰進行排序,是name還是age?重大到小還是從小到大也沒說

這里說類型轉換異常,這是為什么呢?

在第320行,進入320行的源碼

發現,將a數組元素下標runHi的值取出來強轉為Comparable,所以這個類起碼要實現這個接口,才能使他強轉,問題就是現在并沒有實現這個接口,

從大到小排序:

也可以自己實現一個方法:用冒泡排序

但是呢以上的代碼都不太靈活,都已經寫死了,寫了name就只能比較name,寫了age就只能比較age。??

所以,我們可以讓他靈活一點,我想根據年齡比較就年齡比較,想根據姓名比較就姓名比較

我們把Comparator稱為比較器,在這呢是一個年齡比較器

這類的實現并沒有寫在學生類上,他很靈活,可以再寫一個name比較器

還可以加上之前默認的

通過數組傳Comparator

所以在這是可以傳一個比較器的

2.8 Cloneable 接口

Java 中內置了一些很有用的接口, Clonable 就是其中之一.

Object 類中存在一個 clone 方法, 調用這個方法可以創建一個對象的 "拷貝". 但是要想合法調用 clone 方法, 必須要先實現 Clonable 接口, 否則就會拋出 CloneNotSupportedException 異常.

前提:任何一個對象默認都是繼承于Object類的,他是所有類的父類,雙擊shift可搜索Object

例如:

進入Object類

可以發現,Object有clone這個方法,為什么在 . 的時候找不到這個方法??

這里Object是由protected修飾的,只能是不同包子類才能訪問,而且還需要super訪問,Student在Demo3這個路徑底下,Object在Java.lang這個路徑底下

所以就要重寫這里的clone,說是重寫,其實自己的clone方法里面調用了一個super????????

現在就可以調用了

但是呢為什么還是會報錯?

因為是把父類給到子類,向下轉型,需要強轉為Student? ? 那為啥還報錯?

這是異常的原因,后續會講到

現在就可以運行了? ?又為什么運行時報錯了?

要想克隆成功,必須實現一個Cloneable接口

但是呢,我們實現這個接口為什么沒有重寫方法,可進入這個接口源碼

發現,這個接口并沒有一個抽象方法,此時這個接口叫做空接口或者叫做標記接口。只要實現了這個克隆接口,才證明當前類才能被克隆!!!

淺拷貝和深拷貝:

淺拷貝:

在上面代碼中增加一代點代碼

這里只是克隆了student1所指向的對象(Student),并沒有克隆m的值,實際上student2還是指向的是student1? m的值

所以這里的輸出結果,改變了student2的值,student1的值也跟著改變了,這就叫淺拷貝!

深拷貝:

按照以上代碼,我們就需要把m的值跟著克隆一份,就不會修改student1的值了

通過上述代碼發現,是通過super.clone來克隆student1對象,定義一個tmp來接受

但是tmp里面的m并沒有克隆,所以我們需要把m也跟著克隆,那怎么樣才能去克隆m所指向的這個Money呢?? 所以Money這個類也要支持克隆

目前這個m還是student1的m,通過this去調用代表當前對象的m

2.9 抽象類和接口的區別

抽象類和接口都是 Java 中多態的常見使用方式. 都需要重點掌握. 同時又要認清兩者的區別(重要!!! 常見面試題)

核心區別: 抽象類中可以包含普通方法和普通字段, 這樣的普通方法和字段可以被子類直接使用(不必重寫), 而接口中不能包含普通方法, 子類必須重寫所有的抽象方法

如之前寫的 Animal 例子. 此處的 Animal 中包含一個 name 這樣的屬性, 這個屬性在任何子類中都是存在的. 因此此 處的 Animal 只能作為一個抽象類, 而不應該成為一個接口

3. Object類

Object是Java默認提供的一個類。Java里面除了Object類,所有的類都是存在繼承關系的。默認會繼承Object父類。即所有類的對象都可以使用Object的引用進行接收。

例如:

所以在開發之中,Object類是參數的最高統一類型。但是Object類也存在有定義好的一些方法。如下:雙擊shift,搜索Object

3.1?對象比較equals方法

此時,當前類并沒有equals這個方法,那為什么能調用,因為繼承Object的

那為什么是false(equals判斷是否一樣),這里他們比較了兩個對象的地址,所以返回false

進入equals的源碼

可以發現這兩種寫法是一樣的

發現他提供equals沒有實現,我們自己實現一個方法

所以,equals的功能是比較相不相同,在某些情況下,我們需要重寫這個方法!

比如String就重寫了!? Object原生的是比較地址的!!!

結論:比較對象中內容是否相同的時候,一定要重寫equals方法。

3.2 hashcode方法

toString方法的源碼:

我們看到了hashCode()這個方法,他幫我算了一個具體的對象位置,這里面涉及數據結構,但是我們還沒學數據結構,沒法講述,所以我們只能說它是個內存地址。

然后調用Integer.toHexString()方法,將這個地址以16進制輸出。

我們來到hashcode的源碼:

這個方法是由native修飾的,說明底層代碼是由c/c++寫的,會返回一個整數

觀察下面代碼:從代碼上看確實是兩個不同的對象,但是從業務邏輯上來說,認為是同一個人

所以,我們期望這兩個對象放到同一位置,意味著返回的整數值應該是一樣的!!!

但是這里的值并不是一樣的!

所以,我們就要重寫hashcode值

生成hashcode值就是是根據age,name生成,equals就是根據name,age同時一樣來判斷

總結:只要是自定義類型,一定要重寫hashcode方法和equals方法!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/12102.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/12102.shtml
英文地址,請注明出處:http://en.pswp.cn/web/12102.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Leaflet系列——【一】初識Leaflet與Leaflet視圖操作

初識Leaflet(vue3 ) 前言:當你熟悉了openlayer、mapbox、cesium等一些GIS框架之后,對于我們開發來說其實他們的本質就是往瓦片上面疊加圖層、【點、線、面、瓦片、geoJson、熱力圖、圖片、svg等等】都是一層層的Layer圖層&#xf…

MySQL中的多表設計

由于業務之間的相互關聯,所以各個表結構之間也存在著各種聯系 基本分為三種: 一對多 多對多 一對一 外鍵語法 create table 表名( 字段名 數據類型, ... [constraint] 外鍵名稱 foreign key (外鍵字段名&#…

銀川項目外包找邦芒 助力企業減壓增效

銀川邦芒人力項目外包,是指企業將原本由自身承擔的具有基礎性、共性、非核心的IT業務和基于IT的業務流程,委托給專業的外部服務提供商來執行的一種經濟活動。這種全方位的企業用工解決方案,旨在幫助企業優化資源配置、降低成本、提升效率&…

相同的隨機種子CPU和GPU上torch.nn.init.xavier_normal_結果并不一致

相同的隨機種子CPU和GPU上torch.nn.init.xavier_normal_結果并不一致 一.測試代碼二.輸出 在訓練pytorch模型時,相同的隨機種子,不同的服務器上loss并不一樣,通過調試發現這二個平臺的權值也不一樣.單獨測試torch.nn.init.xavier_normal_,發現也不一樣.如果都放在CPU上則二臺服…

Ceph集群擴容及數據再均衡原理分析

用戶文件在Ceph RADOS中存儲、定位過程大概包括:用戶文件切割成對象、對象映射到PG、PG分組PGP、PG映射到OSD。這些過程中,可能涉及了大量概念和變量,而其實它們大部分是通過HASH、CRUSH等算法計算出來的,初始參數可能也就只有這么…

sql實踐

1.從excel導入數據 在excel導入數據時要先在數據庫中創建對應的數據庫表 CREATE TABLE your_table_name (crawl_datetime DATE,url CHAR(255),company_name CHAR(255),company_size CHAR(255),company_type CHAR(255),job_type CHAR(255),job_name CHAR(255),edu CHAR(255),e…

暗區突圍TWITCH掉寶關聯帳號不了 無法關聯帳號 關聯不上

Twitch,作為全球知名的游戲直播平臺,常常攜手熱門游戲如《暗區突圍》舉辦互動活動,為玩家帶來獨特的參與體驗。在這個過程中,“綁定關聯”成為了連接直播觀眾與游戲世界的橋梁。簡單來說,Twitch綁定關聯《暗區突圍》指…

leetcode——鏈表的中間節點

876. 鏈表的中間結點 - 力扣(LeetCode) 鏈表的中間節點是一個簡單的鏈表OJ。我們要返回中間節點有兩種情況:節點數為奇數和節點數是偶數。如果是奇數則直接返回中間節點,如果是偶數則返回第二個中間節點。 這道題的解題思路是&a…

OpenAI 發布了免費的 GPT-4o,國內大模型還有哪些機會?

大家好,我是程序員X小鹿,前互聯網大廠程序員,自由職業2年,也一名 AIGC 愛好者,持續分享更多前沿的「AI 工具」和「AI副業玩法」,歡迎一起交流~ 這是今天在某乎看到一個問題:OpenAI 發完 GPT-4o&…

關閉 Visual Studio Code 項目中 的eslint的語法校驗 lintOnSave: false;; 項目運行起來之后 自動打開瀏覽器 端口

1、在 vue.config.js 配置 一個屬性 lintOnSave: false 2、配置兩個屬性 open: true, // 自動打開瀏覽器 port: 3000 // 端口 port 端口號根據自己的項目實際開發來 配置

Lumina-T2X 一個使用 DiT 架構的內容生成模型,可通過文本生成圖像、視頻、多視角 3D 對象和音頻剪輯。

Lumina-T2X 是一個新的內容生成系列模型,統一使用 DiT 架構。通過文本生成圖像、視頻、多視角 3D 對象和音頻剪輯。 可以在大幅提高生成質量的前提下大幅減少訓練成本,而且同一個架構支持不同的內容生成。圖像質量相當不錯。 由 50 億參數的 Flag-DiT …

structured concurrency

1. 基于 c executions的異步實現 - 從理論到實踐 - 知乎 (zhihu.com)

kubeadm部署k8s v1.30

k8s 1.30主要新功能 kubelet 重啟后穩健的 VolumeManager 重建(SIG Storage) 防止在卷還原過程中未經授權的卷模式轉換(SIG Storage) Pod 調度可用性(SIG Scheduling) PodTopologySpread 中的最小域數&a…

VitePress變成可視化了

VitePressSimple 非技術人員搭建博客的門檻又降低了,這個開源項目把VitePress變成可視化了。 要搭建博客、教程網站,VitePress是門檻最低的方案之一,唯一和技術有關的就是會用到編輯器來操作。 現在好了,VitePressSimple直接把Vit…

Java 枚舉的使用與反射應用

文章目錄 一、定義方式1.1 簡單定義1.2 帶參數定義 二、反射應用1. 反射獲取枚舉常量2. 反射獲取枚舉屬性3. 動態調用枚舉方法4. 動態設置枚舉屬性5. 判斷枚舉類型6. 反射獲取枚舉信息 單例模式:枚舉類型是一種有限實例的類,枚舉常量在定義時就被限定為一…

解決在云服務器上無法使用QQ郵箱發送郵件的問題

最近在做測試demo的時候發現,在本地可以使用qq郵箱的服務來進行郵件的發送,但是把項目部署到云服務器上就沒辦法發送郵件,并且報錯是連接超時: 向xxxxxqq.com用戶發送綁定郵箱驗證碼異常:Mail server connection fail…

leetcode234-Palindrome Linked List

題目 給你一個單鏈表的頭節點 head ,請你判斷該鏈表是否為回文鏈表 。如果是,返回 true ;否則,返回 false 。 示例 1: 輸入:head [1,2,2,1] 輸出:true 分析 可以用快慢指針的方式找到鏈表的…

自用代碼生成器代碼

代碼生成器 pom.xml文件中 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.ap…

【軟件測試】自動化測試 Selenium 篇(一)

一、什么是自動化測試 1、自動化測試介紹 自動化測試指軟件測試的自動化&#xff0c;在預設狀態下運行應用程序或者系統&#xff0c;預設條件包括正常和異常&#xff0c;最后評估運行結果。將人為驅動的測試行為轉化為機器執行的過程。 自動化就相當于將人工測試手段進行轉換…

【激活函數--下】非線性函數與ReLU函數

文章目錄 一、非線性函數在神經網絡中的重要性二、ReLU函數介紹及其實現2.1 ReLU函數概述2.2 ReLU函數的Python實現及可視化 一、非線性函數在神經網絡中的重要性 在神經網絡中&#xff0c;激活函數的選擇對于網絡的性能和能力至關重要。階躍函數和Sigmoid函數除了是激活函數的…