抽象類, 接口, Object類 ---java

目錄

一. 抽象類

1.1 抽象類概念

1.2 抽象類語法?

1.3 抽象類特性

1.4 抽象類的作用?

二. 接口?

2.1 接口的概念

?2.2 語法規則

2.3 接口的使用?

2.4 接口間的繼承

2.5 抽象類和接口的區別?

三. Object類?

3.1 toString() 方法

3.2 對象比較equals()方法?

3.3?hashcode方法?


一. 抽象類

?上述代碼: 在Dog中重寫了Animal中的eat(),? 在Bird中重寫了Animal中的eat()

而我們從來沒有用到過Animal中的eat(), 因為Animal不指代任何一種動物, 所以eat()無意義.?

那么我們是否可以將Animal中的eat()方法簡化呢?下面就引出了我們的抽象方法和抽象類

1.1 抽象類概念

如果 一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類 。?
例如:

例如上述代碼中的Animal中的eat(),?我們可以把它設計成一個 抽象方法(abstract method), 包含抽象方法的類Animal我們稱為 抽象類(abstract class).?

1.2 抽象類語法?

Java 中,一個類如果被 abstract 修飾稱為抽象類,抽象類中被 abstract 修飾的方法稱為抽象方法,抽象方法不用給出具體的實現體。
例如上述代碼,可修改為:

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

1.3 抽象類特性

1. 抽象類不能直接實例化對象

?

// 編譯出錯
Error :( 30 , 23 ) java : Shape 是抽象的 ; 無法實例化

?2. 抽象方法不能是 private

// 編譯出錯
Error :( 4 , 27 ) java : 非法的修飾符組合 : abstract private

?3. 抽象方法不能被finalstatic修飾,因為抽象方法要被子類重寫

// 編譯報錯:
// Error:(20, 25) java: 非法的修飾符組合 : abstract final
// Error:(21, 33) java: 非法的修飾符組合 : abstract static

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

5. 抽象類中不一定包含抽象方法,但是有抽象方法的類一定是抽象類
6. 抽象類中可以有構造方法,供子類創建對象時,初始化父類的成員變量

1.4 抽象類的作用?

抽象類本身不能被實例化 , 要想使用 , 只能創建該抽象類的子類 . 然后讓子類重寫抽象類中的抽象方法. 使用抽象類相當于多了一重編譯器的校驗 .
使用抽象類的場景就如上面的代碼 , 實際工作不應該由父類完成 , 而應由子類完成 . 那么此時如果不小心誤用成父類了, 使用普通類編譯器是不會報錯的 . 但是父類是抽象類就會在實例化的時候提示錯誤 , 讓我們盡早發現問題 .
很多語法存在的意義都是為了 " 預防出錯 ", 例如我們曾經用過的 final 也是類似 . 創建的變量用戶不去修改 , 不就相當于常量嘛? 但是加上 final 能夠在不小心誤修改的時候 , 讓編譯器及時提醒我們 .
充分利用編譯器的校驗 , 在實際開發中是非常有意義的.

二. 接口?

2.1 接口的概念

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

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

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

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

?2.2 語法規則

1. 接口的定義格式與定義類的格式基本相同,將 class 關鍵字換成 interface 關鍵字,就定義了一個接口。
public interface 接口名稱 {
}
提示 :
1. 創建接口時 , 接口的命名一般以大寫字母 I 開頭 .
2. 接口的命名一般使用 " 形容詞 " 詞性的單詞 .
2. 接口中的方法如果沒有被實現, 那么默認為一個抽象方法
public interface 接口名稱 {
????????public void method1 (); //沒加abstract? 但也默認為抽象方法
}

3.? 接口當中的定義的方法, 默認都是public abstract修飾的(只能是public abstract,其他修飾符都會報錯), 接口中的方法是不能在接口中實現的,只能由實現接口的類來實現 .

public interface 接口名稱 {
????????public abstract void method1 (); // public abstract 是固定搭配,可以不寫
????????void method4 ();
// 注意:在接口中上述寫法都是抽象方法,更推薦省略寫法
}

?4. 如果想要有具體的實現, 必須由default或static修飾

5.? 接口當中定義的成員變量, 默認是public static final修飾的

public interface USB {
????????double brand = 3.0 ; // 默認被: final public static 修飾
}
public class TestUSB {
????????public static void main ( String [] args ) {
????????????????System . out . println ( USB . brand ); // 可以直接通過接口名訪問,說明是靜態的
????????????????USB . brand = 2.0 ;
????????????????// 編譯報錯:Error:(12, 12) java: 無法為最終變量 brand 分配值
????????????????// 說明brand具有 final 屬性
????????}
}

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

public class TestUSB {
????????public static void main ( String [] args ) {
????????????????USB usb = new USB ();
????????}
}
// Error:(10, 19) java: day20210915.USB 是抽象的 ; 無法實例化

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

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

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

2.3 接口的使用?

接口不能直接使用,必須要有一個 " 實現類 " " 實現 " 該接口,實現接口中的所有抽象方法。
需要使用implements來關聯
public class 類名稱 implements 接口名稱 {
????????// ...
}

?注: 一個類只能繼承一個普通類/抽象類, 但是可以實現多個接口(有什么特征就實現什么接口)

接下來我們舉個例子:

通過類來表示動物.

?

另外我們再提供一組接口 , 分別表示 " 會飛的 ", " 會跑的 ", " 會游泳的 ".
接下來我們創建幾個具體的動物:
鳥, 是個動物, 會飛會跑
狗, 是個動物, 會跑會游泳
鴨子, 是個動物, 會跑,會游泳, 會飛
注意:一個類實現多個接口時,每個接口中的抽象方法都要實現,否則類必須設置為抽象類
使用:
結果:

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

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

鳥是一種動物 , 具有會跑,會飛的特性 .
狗也是一種動物 , 既能跑 , 也能游泳
鴨子也是一種動物 , 既能跑 , 也能游 , 還能飛
這樣設計有什么好處呢 ? 時刻牢記多態的好處 , 讓程序猿 忘記類型 . 有了接口之后 , 類的使用者就不必關注具體類型, 而只關注某個類是否具備某種能力.甚至參數可以不是 " 動物 ", 只要會跑 !
例如上述代碼, 再定義一個非動物對象
結果為:

只要該對象具有這種性質, 就可以實現對應的接口.?

2.4 接口間的繼承

Java中,類和類之間是單繼承的,一個類可以實現多個接口,接口與接口之間可以多繼承。即:用接口可以達到多繼承的目的
接口可以繼承一個接口 , 達到復用的效果 . 使用 extends 關鍵字 .
例如上述代碼, 青蛙屬于兩棲動物, 我們可以定義一個兩棲動物的接口, 繼承IRun,ISwim接口

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

2.5 抽象類和接口的區別?

抽象類和接口都是 Java 中多態的常見使用方式 . 都需要重點掌握 . 同時又要認清兩者的區別.
核心區別 :
1. 抽象類中可以包含普通方法和普通字段, 這樣的普通方法和字段可以被子類直接使用(不必重寫),
而接口中不能包含普通方法, 子類必須重寫所有的抽象方法
2. 一個類只能繼承一個抽象類, 但是可以同時實現多個接口, 解決了java中不能多繼承的特性
如之前寫的 Animal 例子 . 此處的 Animal 中包含一個 name 這樣的屬性 , 這個屬性在任何子類中都是存在的 . 因此此處的 Animal 只能作為一個抽象類 , 而不應該成為一個接口

三. Object?

Object Java 默認提供的一個類。 Java 里面除了 Object 類,所有的類都是存在繼承關系的。 所有類默認會繼承Object父類。 即所有類的對象都可以使用Object 的引用進行接收。
例如:在傳參時, 我們可以用Object接收
class Person {
}
class Student {
}
public class Test {
????????public static void function ( Object obj ) {
? ? ? ? ? ? ??
????????}
????????public static void main ( String [] args ) {
????????????????function ( new Person ());
????????????????function ( new Student ());
????????}
}

所以在開發之中,Object類是參數的最高統一類型。但是Object類也存在有定義好的一些方法,在子類中可以進行使用。?

對于整個 Object 類中的方法需要實現全部掌握。
本篇博客當中,我們主要來熟悉這幾個方法: toString() 方法, equals() 方法, hashcode() 方法

3.1 toString() 方法

// Object 類中的 toString() 方法實現:
public String toString () {
????????return getClass (). getName () + "@" + Integer . toHexString ( hashCode ());
}
看下述代碼:

打印結果為:

那么println內部是怎么實現的呢?按住ctrl我們點進去可以看到:

傳過去Son類型的son, 用Object接收,發生了向上轉型, 將x傳到了String.valueOf這個方法里.按住Ctrl我們繼續點進去查看:

調用了Object類的toString方法, 按住Ctrl我們進去點進去:

就看到了我們所輸入的結果.?

所以:

我們直接拿來用的這一行代碼 System.out.println(son);? ,實際上是發生了向上轉型, 通過父類也就是Object類中的toString方法實現的.?

那么如果我們在子類中自己定義一個toString方法,是否可以發生重寫呢?

此時輸出的結果為:

?

?答案是肯定的, 即在子類中自己定義一個toString方法,可以重寫Object中的toString方法.

3.2 對象比較equals()方法?

Java 中, == 進行比較時:
a. 如果 == 左右兩側是基本類型變量,比較的是變量中值是否相同
b. 如果 == 左右兩側是引用類型變量,比較的是引用變量地址是否相同
c. 如果要比較對象中內容,必須重寫 Object 中的 equals 方法,因為 equals 方法默認也是按照地址比較的:
// Object 類中的 equals 方法
public boolean equals ( Object obj ) {
????????return ( this == obj ); // 使用引用中的地址直接來進行比較
}

?例如:

class Person {
????????private String name ;
????????private int age ;
????????public Person ( String name , int age ) {
????????????????this . age = age ;
????????????????this . name = name ;
????????}
}
public class Test {
????????public static void main ( String [] args ) { ????????????
????????????????int a = 10 ;
????????????????int b = 10 ;
????????????????System . out . println ( a == b ); // 輸出 true
????????????? ? Person p1 = new Person ( "gaobo" , 20 ) ;
????????????????Person p2 = new Person ( "gaobo" , 20 ) ;
????????????????System . out . println ( p1 == p2 ); // 輸出 false
????????????????System . out . println ( p1 . equals ( p2 )); // 輸出 false
????????}
}

Person類重寫equals方法后,然后比較:

class Person {
...
????????@Override
????????public boolean equals ( Object obj ) {
????????????????if ( obj == null ) {
????????????????????????return false ;
????????????????}
????????????????if ( this == obj ) {
????????????????????????return true ;
????????????????}
????????????????// 不是Person 類對象
????????????????if ( ! ( obj instanceof Person )) {
????????????????????????return false ;
????????????????}
????????Person person = ( Person ) obj ; // 向下轉型,比較屬性值
????????return this . name . equals ( person . name ) && this . age == person . age ;
????????}
}

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

3.3?hashcode方法?

public native int hashCode ();
該方法是一個 native 方法,底層是由 C/C++ 代碼寫的。我們看不到。
我們認為兩個名字相同,年齡相同的對象,將存儲在同一個位置,如果不重寫 hashcode() 方法,我們可以來看示例代碼:
class Person {
????????public String name ;
????????public int age ;
????????public Person ( String name , int age ) {
????????????????this . name = name ;
????????????????this . age = age ;
????????}
}
public class TestDemo4 {
????????public static void main ( String [] args ) {
????????????????Person per1 = new Person ( "haha" , 20 ) ;
????????????????Person per2 = new Person ( "haha" , 20 ) ;
????????????????System . out . println ( per1 . hashCode ());
????????????????System . out . println ( per2 . hashCode ());
????????}
}
// 執行結果
460141958
1163157884
兩個對象的 hash 值不一樣。
像重寫 equals 方法一樣,我們也可以重寫 hashcode() 方法。此時我們再來看看。
class Person {
????????public String name ;
????????public int age ;
????????public Person ( String name , int age ) {
????????????????this . name = name ;
????????????????this . age = age ;
????????}
????????@Override
????????public int hashCode () {
????????????????return Objects . hash ( name , age );
????????}
}
public class TestDemo4 {
????????public static void main ( String [] args ) {
????????????????Person per1 = new Person ( "haha" , 20 ) ;
????????????????Person per2 = new Person ( "haha" , 20 ) ;
????????????????System . out . println ( per1 . hashCode ());
????????????????System . out . println ( per2 . hashCode ());
????????}
}
// 執行結果
460141958
460141958

?哈希值一樣

結論:
1 hashcode 方法用來確定對象在內存中存儲的位置是否相同
2 、事實上 hashCode() 在散列表中才有用,在其它情況下沒用。在散列表中 hashCode() 的作用是獲取對象的散列碼,進而確定該對象在散列表中的位置。

?

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

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

相關文章

免費獲取GPT-4的五種工具

不可否認,由OpenAI帶來的GPT-4已是全球最受歡迎的、功能最強大的大語言模型(LLM)之一。大多數人都需要使用ChatGPT Plus的訂閱服務去訪問GPT-4。為此,他們通常需要每月支付20美元。那么問題來了,如果您不想每月有這筆支…

基于JavaWeb+SpringBoot+Vue醫院管理系統小程序的設計和實現

基于JavaWebSpringBootVue醫院管理系統小程序的設計和實現 源碼獲取入口Lun文目錄前言主要技術系統設計功能截圖訂閱經典源碼專欄[Java 源碼獲取 源碼獲取入口 Lun文目錄 目錄 1系統概述 1 1.1 研究背景 1 1.2研究目的 1 1.3系統設計思想 1 2相關技術 2 2.1微信小程序 2 2.2 …

井蓋位移傳感器廠家批發,守護井蓋安全

窨井蓋廣泛分布于城市街道,其管理效果直接反映了城市治理的現代化程度。根據住房和城鄉建設部發布的《關于進一步加強城市窨井蓋安全管理的通知》,全國各地需加強窨井蓋的安全管理。作為市政基礎設施的一個重要的組成部分,井蓋的管理工作不僅…

去水印網站哪個好?試試這個去水印軟件!

在工作中,我們都曾遇到過圖片水印的困擾。在眾多的在線水印去除工具中,雖然選擇看似豐富,但往往很難找到完全滿足我們需求的那一個。有些工具操作過程繁復,有些工具在處理復雜水印時力不從心,還有些工具在去水印的過程…

【Spring日志】

一.日志作用 1.定位和發現問題 這是日志的主要用途,通過查看日志,我們可以定位問題發生的位置,從而快速的發現問題,分析問題. 2.系統監控 監控幾乎是一個成熟系統的標配,我們可以通過日志記錄這個系統的運行狀態,比如記錄方法的響應時間,響應狀態,通過設置不同的規則,超過閾值就…

【MyBatis <if> <where>標簽介紹】

文章目錄 <if>標簽<where>標簽<foreach>標簽 <if>標簽 <if>標簽允許我們在SQL語句中添加條件判斷。 <if test"condition"><!-- 當條件滿足時執行的SQL語句 --> </if>其中&#xff0c;test屬性是一個表達式&#x…

葡萄酒按酒體如何分類,都有什么特點?

葡萄酒的酒體是指酒液在口腔中的飽滿度和分量感&#xff0c;品酒者常用“輕盈”“厚重”“適中”等詞匯來形容。所以&#xff0c;云倉酒莊的品牌雷盛紅酒分享在葡萄酒分類中還有一個類型&#xff0c;就是按照酒體進行分類。一般分為輕盈型、中等型、飽滿型。 輕盈型&#xff1…

海外https代理ip如何保障信息安全?該怎么選擇?

海外https代理ip是指通信協議為https的海外真實網絡地址ip&#xff0c;通常應用在各種跨境業務中。 一、什么是HTTPS協議 HTTP協議是一個應用層協議&#xff0c;通常運行在TCP協議之上。它是一個明文協議&#xff0c;客戶端發起請求&#xff0c;服務端給出響應的響應。由于網…

表單郵箱密碼登錄 原生+Jquery實現

文章目錄 效果代碼郵箱驗證正則表達式HTMLCSS JS 效果 正確密碼為&#xff1a;123456 點擊登錄按鈕校驗。 代碼 表單校驗 - CodeSandbox 郵箱驗證正則表達式 /(?:[a-z0-9!#$%&*/?^_{|}~-](?:\.[a-z0-9!#$%&*/?^_{|}~-])*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1…

Excel表中合并兩個Sheet的方法?

按AltF11&#xff0c;調出Visual Basic 界面。 在左側窗口中&#xff0c;右鍵選擇“插入”—“模塊”&#xff1a; 將如下代碼粘貼進去&#xff0c;點擊運行按鈕&#xff0c;完成數據表合并。 Sub MergeAllSheetsInThisWorkbook() On Error Resume Next Application.ScreenU…

JOSEF約瑟 熱過載保護繼電器 JR36-160,整定值100-160A

系列型號 JR36-20 1.0-1.6A熱繼電器 JR36-20 0.25-0.35A熱繼電器 JR36-20 0.32-0.5A熱繼電器 JR36-20 0.45-0.72A熱繼電器 JR36-20 0.68-1.1A熱繼電器 JR36-20 1.5-2.4A熱繼電器 JR36-20 2.2-3.5A熱繼電器 JR36-20 3.2-5A熱繼電器 JR36-20 4.5-7.2A熱繼電器 JR36-20 …

【Python 訓練營】N_1 驗證密碼

N_1 驗證密碼 題目 設計一個用戶密碼驗證程序&#xff0c;要求密碼輸入只有3次機會&#xff0c;且密碼中不能包含”*”字符。 分析 需要考慮3個問題&#xff1a;驗證次數、特殊字符和正誤密碼判斷&#xff1b;驗證次數需要使用循環&#xff0c;3個問題需要用到分支結構&…

客戶案例:保障高校郵件安全,守護教育信息安全堡壘

客戶背景 電子科技大學&#xff08;以下簡稱“電子科大”&#xff09;&#xff0c;位于四川省成都市&#xff0c;是一所歷史悠久、實力雄厚的綜合性工業大學。作為我國重點建設的雙一流高校&#xff0c;電子科大在國內外均享有盛譽&#xff0c;其學科涵蓋了理、工、管、文等多…

7.5 Windows驅動開發:監控Register注冊表回調

在筆者前一篇文章《內核枚舉Registry注冊表回調》中實現了對注冊表的枚舉&#xff0c;本章將實現對注冊表的監控&#xff0c;不同于32位系統在64位系統中&#xff0c;微軟為我們提供了兩個針對注冊表的專用內核監控函數&#xff0c;通過這兩個函數可以在不劫持內核API的前提下實…

數組方法reduce的基礎用法和奇怪的用法

Array.prototype.reduce 是 JavaScript 數組方法之一&#xff0c;用于累積數組的各個值&#xff0c;將其簡化為單個值。下面是一些基礎用法和一些可能被認為奇怪或不太常見的用法&#xff1a; 基礎用法&#xff1a; 數組求和&#xff1a; const numbers [1, 2, 3, 4, 5]; c…

Android runtime層是如何通過縮減代碼來縮減內存的

文章目錄 前言&#xff1a;Android 在設備上改進內存的秘密優化編譯器101代碼大小改進消除寫入障礙隱式暫停檢查合并回調其他優化改進代碼下沉循環優化消除死代碼 – SimplifyAlwaysThrows加載存儲消除 – 使用 try catch 塊加載存儲消除 – 使用釋放/獲取操作新的內聯啟發式不…

遞歸回溯剪枝-子集

LCR 079. 子集 - 力扣&#xff08;LeetCode&#xff09; 方法一 1. 決策樹&#xff1a;對于決策樹&#xff0c;思考的角度不同&#xff0c;畫出的決策樹也會不同&#xff0c;這道題可以從兩個角度來畫決策樹。 2. 考慮全局變量的使用&#xff1a; 使用全局變量 List<List&…

Python 基礎【五】--數據類型-序列【2023.11.24】

1.定義 Python 中的序列是一塊可存放多個值的連續內存空間&#xff0c;所有值按一定順序排列&#xff0c;每個值所在位置都有一個編號&#xff0c;稱其為索引&#xff0c;我們可以通過索引訪問其對應值。 list1 [Google, Runoob, 1997, 2000] list2 [1, 2, 3, 4, 5 ] list3…

馬克思主義基本原理課后題答案

吐血整理馬原word版課后題答案&#xff0c;大家可以自行修改&#xff0c;持續更新中... 【限于篇幅原因&#xff0c;需要的同學可以點贊收藏后&#x1f44d;&#xff0c;掃碼下方的公眾號&#xff0c;回復相應關鍵詞&#xff08;馬原&#xff09;自行領取?~】

【05】ES6:函數的擴展

一、函數參數的默認值 ES6 允許為函數的參數設置默認值&#xff0c;即直接寫在參數定義的后面。 1、基本用法 默認值的生效條件 不傳參數&#xff0c;或者明確的傳遞 undefined 作為參數&#xff0c;只有這兩種情況下&#xff0c;默認值才會生效。 注意&#xff1a;null 就…