深入淺出探究Java多態(tài)的實(shí)現(xiàn)和應(yīng)用
多態(tài)是指同一操作作用于不同的對(duì)象上,能產(chǎn)生不同的解釋和不同的執(zhí)行方式,通俗來(lái)講就是用一種類型的變量來(lái)引用不同的對(duì)象,從而調(diào)用不同的方法,產(chǎn)生不同的行為。多態(tài)是實(shí)現(xiàn)面向?qū)ο蟮能浖夹g(shù)中必不可少的一個(gè)內(nèi)容。
繼承和多態(tài)
讓我們以一只動(dòng)物為例:狗是一種動(dòng)物,它會(huì)跑;貓也是一種動(dòng)物,它會(huì)走。如果我們想用一個(gè)方法來(lái)描述它們的運(yùn)動(dòng)行為,該怎么做呢?
我們可以先定義一個(gè) Animal 類,里面包含一個(gè) move() 方法,來(lái)描述它們共同的運(yùn)動(dòng)方式:
public class Animal { public void move() { System.out.println("動(dòng)物正在移動(dòng)"); } }
然后,我們可以在 Animal 的子類中,重寫 move() 方法,以實(shí)現(xiàn)不同的運(yùn)動(dòng)方式:
public class Dog extends Animal { public void move() { System.out.println("小狗在跑"); } } public class Cat extends Animal { public void move() { System.out.println("小貓?jiān)谧?); } }
這里我們讓 Dog 類重寫了 move() 方法,實(shí)現(xiàn)了“跑”這種運(yùn)動(dòng)方式;而 Cat 類重寫了 move() 方法,實(shí)現(xiàn)了“走”這種運(yùn)動(dòng)方式。
最后,我們可以在主函數(shù)中,定義一個(gè) Animal 類型的變量,并分別用 Dog 和 Cat 的實(shí)例來(lái)賦值,這樣我們就可以用相同的方法名 move() 來(lái)調(diào)用不同的實(shí)現(xiàn),即實(shí)現(xiàn)多態(tài)的效果:
public class Test { public static void main(String args[]) { Animal animal = new Animal(); Animal dog = new Dog(); Animal cat = new Cat(); animal.move(); // 輸出動(dòng)物正在移動(dòng) dog.move(); // 輸出小狗在跑 cat.move(); // 輸出小貓?jiān)谧? } }
在上述示例中,我們定義了 Animal 父類和 Dog、Cat 兩個(gè)子類。在主函數(shù)中,我們分別聲明了一個(gè)父類對(duì)象、一個(gè) Dog 對(duì)象和一個(gè) Cat 對(duì)象。當(dāng)我們調(diào)用它們的 move() 方法時(shí),表示動(dòng)物正在移動(dòng)、小狗在跑和小貓?jiān)谧撸@就是多態(tài)的實(shí)現(xiàn)原理。
接口和多態(tài)
除了繼承,接口也可以幫助我們實(shí)現(xiàn)多態(tài)的功能。接口是指一組方法的集合,類可以實(shí)現(xiàn)這些方法并重寫它們。和繼承不同的是,一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,從而實(shí)現(xiàn)多態(tài)的效果。
例如,我們可以定義一個(gè)接口 Run,其中包含一個(gè) run() 方法,它表示一些可以奔跑的東西。然后我們可以在一個(gè)類中實(shí)現(xiàn)這個(gè)接口,并實(shí)現(xiàn)其中的方法,以表示具體的奔跑行為。最后,在代碼中,我們可以用接口類型來(lái)聲明一個(gè)變量,從而實(shí)現(xiàn)對(duì)多個(gè)實(shí)現(xiàn)類的引用。
下面是一個(gè)簡(jiǎn)單的 Java 程序示例:
public interface Run { void run(); } public class Dog implements Run { public void run() { System.out.println("小狗在跑"); } } public class Cat implements Run { public void run() { System.out.println("小貓?jiān)谧?); } } public class Test { public static void main(String[] args) { Run dog = new Dog(); Run cat = new Cat(); dog.run(); // 輸出小狗在跑 cat.run(); // 輸出小貓?jiān)谧? } }
在上述示例中,我們定義了一個(gè) Run 接口,它包含一個(gè) run() 方法。然后我們可以在一個(gè)類中實(shí)現(xiàn)這個(gè)接口,并實(shí)現(xiàn)其中的方法,以表示具體的奔跑行為。最后,在主函數(shù)中,我們分別聲明了一個(gè) Dog 類型、一個(gè) Cat 類型的變量,并用它們的實(shí)例進(jìn)行賦值和調(diào)用,從而實(shí)現(xiàn)多態(tài)的效果。
方法重載和多態(tài)
方法重載是指在同一個(gè)類或一個(gè)類的繼承結(jié)構(gòu)中,使用相同的方法名,但要求參數(shù)類型或個(gè)數(shù)不同,使得一個(gè)類擁有多個(gè)具有不同參數(shù)的方法,自動(dòng)匹配到不同的方法實(shí)現(xiàn)。方法的重載可以讓我們更好地重用代碼和實(shí)現(xiàn)更加靈活的方法調(diào)用。
例如,我們可以重載一個(gè) add() 方法,使得它既可以實(shí)現(xiàn)整數(shù)相加,又可以實(shí)現(xiàn)小數(shù)相加。在代碼中,我們可以用相同的方法名 add() 來(lái)調(diào)用這兩種不同的方法,最終調(diào)用的方法取決于實(shí)參類型。
下面是一個(gè)簡(jiǎn)單的 Java 程序示例:
public class Calculation { public void add(int a, int b) { System.out.println("兩個(gè)整數(shù)相加的結(jié)果是:" + (a + b)); } public void add(double a, double b) { System.out.println("兩個(gè)小數(shù)相加的結(jié)果是:" + (a + b)); } } public class Test { public static void main(String args[]) { Calculation calculation = new Calculation(); calculation.add(10, 20); // 輸出兩個(gè)整數(shù)相加的結(jié)果是:30 calculation.add(1.2, 3.4); // 輸出兩個(gè)小數(shù)相加的結(jié)果是:4.6 } }
在上述示例中,我們定義了一個(gè) Calculation 類,其中包含了兩個(gè)相同名稱、但參數(shù)類型不同的 add() 方法,一個(gè)是將兩個(gè)整數(shù)相加,另一個(gè)是將兩個(gè)小數(shù)相加。在主函數(shù)中,我們分別調(diào)用這兩個(gè)方法,并分別輸出它們的結(jié)果。這展示了編譯時(shí)多態(tài)的實(shí)現(xiàn)原理。
方法覆蓋和多態(tài)
方法覆蓋是指子類重寫了父類中的某個(gè)方法,并且子類中的方法和父類中的方法具有相同的方法名稱、返回類型和參數(shù)列表。當(dāng)我們使用父類類型來(lái)聲明一個(gè)變量,并將其賦值為子類的實(shí)例時(shí),該變量將會(huì)調(diào)用子類中的方法,實(shí)現(xiàn)動(dòng)態(tài)多態(tài)的效果。
例如,我們可以定義一個(gè)新的類 Panther,它繼承自 Animal 類,然后重寫了 move() 方法,以實(shí)現(xiàn)新的運(yùn)動(dòng)方式。最后,在主函數(shù)中,我們可以用 Animal 類型來(lái)聲明一個(gè)變量,并將其分別賦值為 Dog、Cat 和 Panther 的實(shí)例,用 move() 方法來(lái)調(diào)用它們的運(yùn)動(dòng)行為,實(shí)現(xiàn)動(dòng)態(tài)多態(tài)的效果。
下面是一個(gè)簡(jiǎn)單的 Java 程序示例:
public class Panther extends Animal { public void move() { System.out.println("黑豹在奔跑"); } } public class Test { public static void main(String[] args) { Animal animal1 = new Animal(); Animal animal2 = new Dog(); Animal animal3 = new Cat(); Animal animal4 = new Panther(); animal1.move(); // 輸出動(dòng)物正在移動(dòng) animal2.move(); // 輸出小狗在跑 animal3.move(); // 輸出小貓?jiān)谧? animal4.move(); // 輸出黑豹在奔跑 } }
在上述示例中,我們定義了一個(gè) Panther 類,它繼承自 Animal 類,然后重寫了 move() 方法,以實(shí)現(xiàn)新的運(yùn)動(dòng)方式。在主函數(shù)中,我們分別聲明了一個(gè)父類對(duì)象、一個(gè) Dog 對(duì)象、一個(gè) Cat 對(duì)象和一個(gè) Panther 對(duì)象,并用它們的實(shí)例進(jìn)行賦值和調(diào)用,最終調(diào)用的方法取決于實(shí)際對(duì)象的類型,這就是運(yùn)行時(shí)多態(tài)的實(shí)現(xiàn)原理。
多態(tài)原理分析
多態(tài)可以分為編譯時(shí)多態(tài)和運(yùn)行時(shí)多態(tài)兩種。
運(yùn)行時(shí)多態(tài)
運(yùn)行時(shí)多態(tài)又稱動(dòng)態(tài)多態(tài),是指在程序運(yùn)行期間根據(jù)對(duì)象的類型來(lái)確定方法的調(diào)用。運(yùn)行時(shí)多態(tài)是通過(guò)方法重寫和接口實(shí)現(xiàn)來(lái)實(shí)現(xiàn)的。
上述的動(dòng)物類 Animal,它擁有一個(gè) move() 方法來(lái)描述動(dòng)物的運(yùn)動(dòng)行為,這個(gè)move() 具體調(diào)用哪個(gè)方法(Animal/Dog/Cat)在編譯期間是不知道的,它是在運(yùn)行期間確定的,在運(yùn)行期間給他傳入什么對(duì)象它就調(diào)用什么方法。
編譯時(shí)多態(tài)
編譯時(shí)多態(tài)又稱靜態(tài)多態(tài),是指在編譯期間就確定了方法的調(diào)用。編譯時(shí)多態(tài)是通過(guò)方法重載來(lái)實(shí)現(xiàn)的,即同一個(gè)類中有多個(gè)名稱、參數(shù)不同的方法,編譯器在調(diào)用這些方法時(shí),會(huì)根據(jù)實(shí)參類型的不同來(lái)匹配相應(yīng)的方法。
通過(guò)JDBC理解動(dòng)態(tài)
JDBC 是 Java 數(shù)據(jù)庫(kù)連接的標(biāo)準(zhǔn)接口,它允許 Java 應(yīng)用程序通過(guò)統(tǒng)一的接口訪問(wèn)不同的數(shù)據(jù)庫(kù)。使用 JDBC 可以連接多種數(shù)據(jù)庫(kù),如 MySQL、Oracle、SQL Server 等,這就要求 JDBC 具有語(yǔ)言無(wú)關(guān)性,可以在運(yùn)行時(shí)動(dòng)態(tài)確定將要連接的數(shù)據(jù)庫(kù)類型,這樣才能支持多種數(shù)據(jù)庫(kù)的連接。
JDBC 中用到的多態(tài)主要是運(yùn)行時(shí)多態(tài)。JDBC 接口定義了一些通用的方法和接口,如 Connection、Statement、ResultSet 等,它們都是抽象類或接口。具體的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序?qū)崿F(xiàn)了這些方法和接口,通過(guò)實(shí)現(xiàn)這些方法和接口,實(shí)現(xiàn)了連接到具體的數(shù)據(jù)庫(kù)。在連接數(shù)據(jù)庫(kù)時(shí),我們通過(guò) DriverManager 的 getConnection() 方法獲取 Connection 對(duì)象,此時(shí)是用的是 JDBC 接口,而不是具體的數(shù)據(jù)庫(kù)驅(qū)動(dòng)連接,只有在使用 Connection 對(duì)象的時(shí)候才會(huì)動(dòng)態(tài)判斷實(shí)際使用的數(shù)據(jù)庫(kù)類型。以下是一個(gè)簡(jiǎn)單的 JDBC 連接 MySQL 數(shù)據(jù)庫(kù)的示例代碼:
String url = "jdbc:mysql://localhost:3306/test"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url, username, password);
在上述代碼中,我們只是通過(guò) JDBC 接口連接到 MySQL 數(shù)據(jù)庫(kù),并沒(méi)有使用具體的 MySQL 驅(qū)動(dòng)程序。當(dāng)我們調(diào)用 conn.prepareStatement() 方法時(shí),此時(shí)才根據(jù)具體的數(shù)據(jù)庫(kù)類型獲取到一個(gè)實(shí)現(xiàn)了 PreparedStatement 接口的對(duì)象,例如 MySQLPreparedStatement。這就是在運(yùn)行時(shí)動(dòng)態(tài)確定要使用的數(shù)據(jù)庫(kù)類型,實(shí)現(xiàn)了運(yùn)行時(shí)多態(tài)的效果。
總之,JDBC 中充分利用了 Java 的多態(tài)特性,通過(guò)動(dòng)態(tài)綁定技術(shù),實(shí)現(xiàn)了在不同數(shù)據(jù)庫(kù)之間切換時(shí)的語(yǔ)言無(wú)關(guān)性。JDBC 連接的抽象設(shè)計(jì),可以讓我們編寫一次連接代碼,就可以連接多個(gè)數(shù)據(jù)庫(kù),實(shí)現(xiàn)了代碼復(fù)用和可擴(kuò)展性。
總結(jié)
多態(tài)是 Java 面向?qū)ο缶幊讨械闹匾拍睢K试S我們?cè)诰帉懘a時(shí),只需要知道一個(gè)對(duì)象的類型,而無(wú)需知道它所具體屬于的子類類型。在 Java 中,多態(tài)的實(shí)現(xiàn)原理主要有兩種方式:運(yùn)行時(shí)多態(tài)和編譯時(shí)多態(tài)。前者是通過(guò)方法的重寫實(shí)現(xiàn)的,后者則是通過(guò)方法的重載實(shí)現(xiàn)的。同時(shí),多態(tài)也讓 Java 的代碼更加靈活、可擴(kuò)展性更強(qiáng)。
以上就是深入淺出探究Java多態(tài)的實(shí)現(xiàn)和應(yīng)用的詳細(xì)內(nèi)容,更多關(guān)于Java多態(tài)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java中int、double、char等變量的取值范圍詳析
這篇文章主要給大家介紹了關(guān)于java中int、double、char等變量取值范圍的相關(guān)資料,每個(gè)變量都給出了詳細(xì)的實(shí)例代碼,對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-10-10Spring?Boot?配置文件之類型、加載順序與最佳實(shí)踐記錄
Spring?Boot?的配置文件是靈活且強(qiáng)大的工具,通過(guò)合理的配置管理,可以讓應(yīng)用開發(fā)和部署更加高效,無(wú)論是簡(jiǎn)單的屬性配置,還是復(fù)雜的多環(huán)境管理,Spring?Boot都提供了便捷的解決方案,本文介紹Spring?Boot?配置文件:類型、加載順序與最佳實(shí)踐,感興趣的朋友一起看看吧2025-04-04解析springboot集成AOP實(shí)現(xiàn)日志輸出的方法
如果這需要在每一個(gè)controller層去寫的話代碼過(guò)于重復(fù),于是就使用AOP定義切面 對(duì)其接口調(diào)用前后進(jìn)行攔截日志輸出。接下來(lái)通過(guò)本文給大家介紹springboot集成AOP實(shí)現(xiàn)日志輸出,需要的朋友可以參考下2021-11-11SpringBoot實(shí)現(xiàn)輕量級(jí)動(dòng)態(tài)定時(shí)任務(wù)管控及組件化的操作步驟
文章介紹了一種在SpringBoot中實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)的解決方案,基于COLA架構(gòu)理論,封裝到了組件層,該組件支持類級(jí)別和方法級(jí)別的定時(shí)任務(wù)注冊(cè),并提供了易用性和擴(kuò)展性,組件使用Maven形式引入,并且可以通過(guò)YAML配置文件進(jìn)行設(shè)置,感興趣的朋友一起看看吧2024-11-11JAVA?兩個(gè)類同時(shí)實(shí)現(xiàn)同一個(gè)接口的方法(三種方法)
在Java中,兩個(gè)類同時(shí)實(shí)現(xiàn)同一個(gè)接口是非常常見(jiàn)的,接口定義了一組方法,實(shí)現(xiàn)接口的類必須提供這些方法的具體實(shí)現(xiàn),以下將展示如何實(shí)現(xiàn)這一要求,并提供具體的代碼示例,需要的朋友可以參考下2024-08-08java實(shí)現(xiàn) 微博登錄、微信登錄、qq登錄實(shí)現(xiàn)代碼
這篇文章主要介紹了java實(shí)現(xiàn) 微博登錄、微信登錄、qq登錄實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2016-10-10