java基礎(chǔ)的詳細(xì)了解第八天
1、多態(tài)性
多態(tài)性是面向?qū)ο蟮淖詈笠粋€(gè)特征,它本身主要分為兩個(gè)方面:
方法的多態(tài)性:重載與覆寫(xiě)
1、重載:同一個(gè)方法名稱(chēng),根據(jù)參數(shù)類(lèi)型以及個(gè)數(shù)完成不同功能;
2、覆寫(xiě):通一個(gè)方法,根據(jù)操作的子類(lèi)不同,所完成的功能也不同。
對(duì)象的多態(tài)性:父子類(lèi)對(duì)象的轉(zhuǎn)換。
1、向上轉(zhuǎn)型:子類(lèi)對(duì)象變?yōu)楦割?lèi)對(duì)象,父類(lèi) 父類(lèi)對(duì)象 = 子類(lèi) 子類(lèi)對(duì)象 自動(dòng);
2、向上轉(zhuǎn)型:父類(lèi)對(duì)象變?yōu)樽宇?lèi)對(duì)象,格式:子類(lèi) 子類(lèi)對(duì)象 = (子類(lèi))父類(lèi)實(shí)例,強(qiáng)制;
class A{ public void print(){ System.out.println("A輸出"); } } class B extends A{ public void print(){ System.out.println("B輸出"); } } public class TestDemo1{ public static void main(String args[]){ B b = new B(); //B輸出 b.print(); } }
這種操作主要觀察兩點(diǎn):
1、 看實(shí)例化的是哪一類(lèi)(new);
2 、看new的這個(gè)類(lèi)之中是否被覆寫(xiě)了父類(lèi)調(diào)用的方法。
1.1 向上轉(zhuǎn)型
public class TestDemo1{ public static void main(String args[]){ A a = new B(); //向上轉(zhuǎn)型 //B輸出 a.print(); } }
1.2 向下轉(zhuǎn)型
public class TestDemo1{ public static void main(String args[]){ A a = new B(); //向上轉(zhuǎn)型 B b = (B) a; //向下轉(zhuǎn)型 b.print(); } }
public class TestDemo1{ public static void main(String args[]){ A a = new A(); //沒(méi)有轉(zhuǎn)型 B b = (B) a; //向下轉(zhuǎn)型 b.print(); } } /* Exception in thread "main" java.lang.ClassCastException: A cannot be cast to B at DuoTaiXing.main(TestDemo1.java:14) */
以上的程序在編譯的時(shí)候沒(méi)有發(fā)生任何錯(cuò)誤信息,但是在執(zhí)行的時(shí)候出現(xiàn)了“ClassCastException”錯(cuò)誤提示,表示的是類(lèi)轉(zhuǎn)換異常,即:兩個(gè)沒(méi)有關(guān)系的類(lèi)互相發(fā)生了對(duì)象的強(qiáng)制轉(zhuǎn)型。
轉(zhuǎn)型的因素:
- 在實(shí)際工作之中,對(duì)象的向上轉(zhuǎn)型為主要使用,向上轉(zhuǎn)型之后,多有方法以父類(lèi)的方法為主,但是具體的實(shí)現(xiàn),還是要看子類(lèi)是否覆寫(xiě)了此方法;。
- 向下轉(zhuǎn)型,因?yàn)樵谶M(jìn)行向下轉(zhuǎn)型操作之前,一定要首先發(fā)生向上轉(zhuǎn)型,以建立兩個(gè)對(duì)象之間的聯(lián)系,如果沒(méi)有這種聯(lián)系,是不可能發(fā)生向下轉(zhuǎn)型的,一旦發(fā)生了運(yùn)行中就會(huì)出現(xiàn)“ClassCastException”當(dāng)需要調(diào)用子類(lèi)自己特殊定義方法的時(shí)候,菜需要向下轉(zhuǎn)型。
- 不轉(zhuǎn)型,在一些資源較少的時(shí)候,如:移動(dòng)開(kāi)發(fā)。
class A{ public void print(){ System.out.println("A輸出"); } } class B extends A{ public void print(){ System.out.println("B輸出"); } public void funB(){ System.out.println("funB"); } } public class TestDemo1{ public static void main(String args[]){ A a = new B(); //向上轉(zhuǎn)型 System.out.println(a instanceof A); System.out.println(a instanceof B); if (a instanceof B){ B b = (B) a; b.funB(); } } } /* true true funB */
為了日后的操作方便,在編寫(xiě)代碼的時(shí)候,盡量不要去執(zhí)行向下的轉(zhuǎn)型操作,子類(lèi)盡量不要去擴(kuò)充新的方法名稱(chēng)(父類(lèi)沒(méi)有的方法名稱(chēng)),依據(jù)父類(lèi)定義的操作完善方法。
例題:利用對(duì)象向上轉(zhuǎn)型完成
class A{ public void print(){ System.out.println("A輸出"); } } class B extends A{ public void print(){ System.out.println("B輸出"); } } class C extends A{ public void print(){ System.out.println("C輸出"); } } public class TestDemo2{ public static void main(String args[]){ fun(new B()); fun(new C()); } public static void fun(A a){ a.print(); } }
這樣以來(lái)就得到了類(lèi)型的統(tǒng)一,就算有再多的子類(lèi)出現(xiàn),方法或者是類(lèi)也不需要進(jìn)行修改了,但是在這塊必須強(qiáng)調(diào)的是:子類(lèi)操作的過(guò)程之中,盡量向父類(lèi)靠攏。
以后所有的代碼之中,都會(huì)存在對(duì)象的轉(zhuǎn)型問(wèn)題,并且向上轉(zhuǎn)型居多。
在日后的所有開(kāi)發(fā)之中,像之前程序那樣,一個(gè)類(lèi)去繼承另外一個(gè)已經(jīng)實(shí)現(xiàn)好的類(lèi)的情況,是不可能出現(xiàn)的。即:一個(gè)類(lèi)不能去繼承一個(gè)已經(jīng)實(shí)現(xiàn)好的類(lèi),只能繼承抽象類(lèi)或?qū)崿F(xiàn)接口。
2、抽象類(lèi)
在以后你進(jìn)行的項(xiàng)目開(kāi)發(fā)中,絕對(duì)不要出現(xiàn)一個(gè)類(lèi)繼承一個(gè)已經(jīng)實(shí)現(xiàn)好的類(lèi)。
對(duì)象多態(tài)性的核心本質(zhì)在于方法的覆寫(xiě),這樣的操作有些不合要求,所以要對(duì)子類(lèi)的方法進(jìn)行強(qiáng)制的要求就必須采用我們的抽象類(lèi)進(jìn)行實(shí)現(xiàn)。
2.1 抽象類(lèi)的基本概念
普通類(lèi)就是一個(gè)完善的功能類(lèi),可以直接產(chǎn)生對(duì)象并且可以使用,里面的方法都是帶有方法體的,而抽象類(lèi)之中最大的特點(diǎn)是包含了抽象方法,而抽象方法是只聲明而未實(shí)現(xiàn)(沒(méi)有方法體)的方法,而抽象方法定義的時(shí)候要使用abstract關(guān)鍵字完成,而抽象方法一定要在抽象類(lèi)之中,抽象類(lèi)要使用是用abstract聲明。
abstract class A{ private String msg = "www.baidu.com";//屬性 public void print(){ //普通方法 System.out.println(msg); } //{}為方法體,所有的抽象方法上是不包含有方法體的 public abstract void fun() ; //抽象方法 } public class ChouXiang{ public static void main(String args[]){ /* ChouXiang.java:12: 錯(cuò)誤: A是抽象的; 無(wú)法實(shí)例化 A a =new A(); ^ 1 個(gè)錯(cuò)誤 */ A a =new A(); } }
抽象類(lèi)比普通類(lèi)多了抽象方法而已,沒(méi)有上面特殊的。
抽象方法為什么不能實(shí)例化對(duì)象?
抽象類(lèi)中包含抽象方法,而抽象方法與普通方法最大的區(qū)別就是沒(méi)有方法體,不知道具體的實(shí)現(xiàn),而如果產(chǎn)生了實(shí)例化就意味著以可以調(diào)用類(lèi)中的所有操作。
抽象類(lèi)的使用原則:
- 所有抽象類(lèi)必須要含有子類(lèi)抽象類(lèi)的子類(lèi)
- 必須覆寫(xiě)抽象中的全部抽象方法——方法覆寫(xiě)一定要考慮到權(quán)限問(wèn)題,抽象方法可以使用任意權(quán)限,要求權(quán)限盡量public
- 抽象對(duì)象可以通過(guò)對(duì)象多態(tài)性,利用子類(lèi)為其實(shí)現(xiàn)實(shí)例化
abstract class A{ private String msg = "www.baidu.com";//屬性 public void print(){ //普通方法 System.out.println(msg); } //{}為方法體,所有的抽象方法上是不包含有方法體的 public abstract void fun() ; //抽象方法 } //一個(gè)子類(lèi)只能夠利用extends來(lái)繼續(xù)繼承抽象類(lèi),所以依然存在單繼承局限 class B extends A{//定義抽象類(lèi)的子類(lèi) public void fun(){ System.out.println("Hello"); } } public class ChouXiang{ public static void main(String args[]){ A a =new B();//向上轉(zhuǎn)型 a.print(); a.fun(); } }
通過(guò)以上的一個(gè)程序,現(xiàn)在就可以清楚的發(fā)現(xiàn),與之前類(lèi)不一樣的是,抽象類(lèi)定義出了子類(lèi)必須要覆寫(xiě)的方法,而之前的類(lèi)子類(lèi)可以有選擇性的來(lái)決定是否覆寫(xiě)。而且可以發(fā)現(xiàn),抽象類(lèi)實(shí)際上就比普通類(lèi)多了一些抽象方法而已,其他的定義和普通類(lèi)完全一樣。如果把普通類(lèi)比喻成一盤(pán)炒熟的菜,那么抽象類(lèi)就是一盤(pán)半成品。
關(guān)于抽象類(lèi)的若干中疑問(wèn)?
1、抽象類(lèi)能否使用final定義?
不能,因?yàn)閒inal定義的類(lèi)不能有子類(lèi),而抽象類(lèi)必須有子類(lèi)。
2、抽象類(lèi)之中能否包含構(gòu)造方法?
可以,因?yàn)槌橄箢?lèi)之中除了包含抽象方法之外,還包含了普通方法和屬性,而屬性一定要在構(gòu)造方法執(zhí)行完畢之后才可以進(jìn)行初始化操作;
3、抽象類(lèi)之中能否不包含抽象方法?
可以,抽象類(lèi)之中可以沒(méi)有抽象方法,但是反過(guò)來(lái)來(lái)講,如果有抽象,則一定是抽象類(lèi)。即使抽象類(lèi)之中沒(méi)有抽象方法也不能被直接實(shí)例化。
4、抽象類(lèi)能否使用static聲明?
如過(guò)定義的是外部抽象類(lèi),則不能夠使用static聲明,可是如果定義的是內(nèi)部類(lèi),那么這個(gè)內(nèi)部的抽象類(lèi)使用了static聲明之后,就表示一個(gè)外部的抽象類(lèi)。
abstract class A{ private String str = "Hello,China"; static abstract class B{ public abstract void print(); } } class C extends A.B{ public void print(){ System.out.println("你好,中國(guó)"); } } public class ChouXiang{ public static void main(String args[]){ A a =new B();//向上轉(zhuǎn)型 a.print(); } }
結(jié)論:如果構(gòu)造方法沒(méi)有執(zhí)行,類(lèi)中對(duì)象中屬性一定都是其對(duì)應(yīng)數(shù)據(jù)類(lèi)型的默認(rèn)值。
抽象類(lèi)的最大特點(diǎn)在于強(qiáng)制規(guī)定了子類(lèi)的實(shí)現(xiàn)結(jié)構(gòu)。
3、接口
抽象類(lèi)和普通類(lèi)最大的特點(diǎn)就是約定了子類(lèi)的實(shí)現(xiàn)要求:但是抽象類(lèi)有一個(gè)缺點(diǎn)——單繼承局限,如果要想要求以及避免單繼承局限,就需要使用接口。在以后的開(kāi)發(fā)中,接口優(yōu)先,在一個(gè)操作中既可以使用抽象類(lèi)又可以使用我們的接口,優(yōu)先考慮接口。
3.1 接口的基本概念
接口就是一個(gè)抽象方法和全局常量的集合,屬于一種特殊的類(lèi),如果一個(gè)類(lèi)定義的時(shí)候全部由抽象方法和全局常量所組成的話,那么這種類(lèi)就稱(chēng)為接口,但是接口是使用interface關(guān)鍵字定義的。
interface A{//定義接口 public static final String INFO="Hello,World"; public abstract void print(); } interface B{ public abstract void get(); }
那么在接口之中,也同樣存在了抽象方法,很明顯,接口對(duì)象無(wú)法進(jìn)行對(duì)象的實(shí)例化操作,那么接口的使用原則如下:
1、每一個(gè)接口必須定義子類(lèi),子類(lèi)使用implement關(guān)鍵字實(shí)現(xiàn)接口;
2、接口的子類(lèi)(如果不是抽象類(lèi))則必須覆寫(xiě)接口之中所定義的全部抽象方法;
3、利用接口的子類(lèi),采用對(duì)象的向上轉(zhuǎn)型方式,進(jìn)行接口對(duì)象的實(shí)例化操作。
在Java之中每一個(gè)抽象類(lèi)都可以實(shí)現(xiàn)多個(gè)接口,但是反過(guò)來(lái)講,一個(gè)接口卻不能繼承抽象類(lèi),可是Java之中,一個(gè)接口卻可以同時(shí)繼承多個(gè)接口,以實(shí)現(xiàn)接口的多繼承操作。
//因?yàn)榻涌诤皖?lèi)的定義命名要求相同,所以為了區(qū)分接口和類(lèi) //建議在所以的接口前面追加一個(gè)字母I interface IMessage{ public static final String MSG = "www.baidu.com"; public abstract void print();//抽象方法 } interface INews{ public abstract String get(); } class MessageImpl implements IMessage,INews{ public void print(){ System.out.println("IMessage中print方法:" +IMessage.MSG); } public String get(){ return "INews中g(shù)et方法:" + IMessage.MSG; } } class NewsImpl implements INews{ public String get(){ return null; } } public class InFa{ public static void main(String args[]){ IMessage ms = new MessageImpl(); //InFa ms.print(); INews m = new MessageImpl(); //INews中g(shù)et方法:www.baidu.com System.out.println(m.get()); /* Exception in thread "main" java.lang.ClassCastException: NewsImpl cannot be cast to IMessage at InFa.main(InFa.java:33) 轉(zhuǎn)換異常 */ INews mn = new NewsImpl(); IMessage m1 = (IMessage) mn; System.out.println(mn.get()); } }
但是需要說(shuō)明的是:接口之中的全部組成就是抽象方法和全局常量,那么在開(kāi)發(fā)之中一下的兩種定義接口的最終效果是完全一樣的:
3.2 接口的使用限制
完整定義:
interface A{ public static final String INFO="接口A"; public abstract void print(); }
簡(jiǎn)化定義:
interface A{//定義接口 public String INFO="接口A"; public void print(); }
接口之中所有訪問(wèn)權(quán)限只有一種:public,即:定義接口方法的時(shí)候就算沒(méi)寫(xiě)上public,最終也是public.
1.在以后的編寫(xiě)接口的時(shí)候,大部分的接口里面只會(huì)提供抽象方法,很少在接口里面看見(jiàn)許多的全局常量。很多時(shí)候防止避免開(kāi)發(fā)者出現(xiàn)混亂,所以接口的方法都會(huì)加上public。
2.當(dāng)一個(gè)子類(lèi)需要實(shí)現(xiàn)接口又需要繼承抽象類(lèi)的時(shí)候,請(qǐng)先使用extends繼承一個(gè)抽象類(lèi),再使用implements實(shí)現(xiàn)多個(gè)接口。
//因?yàn)榻涌诤皖?lèi)的定義命名要求相同,所以為了區(qū)分接口和類(lèi) //建議在所以的接口前面追加一個(gè)字母I interface INews{ public String get();//抽象方法 } //可以再類(lèi)上進(jìn)行明確描述,在以后的開(kāi)發(fā)之中也經(jīng)常出現(xiàn)以下的命名習(xí)慣 abstract class AbstractMessage{ //只有接口中的abstract中才可以省略,抽象類(lèi)中的不能省略 public abstract void print(); } class NewsImpl extends AbstractMessage implements INews{ public String get(){ return "www.baidu.com"; } public void print(){} //有方法體就叫覆寫(xiě) } public class InFa1{ public static void main(String args[]){ INews news = new NewsImpl(); System.out.println(news.get()); //NewsImpl是抽象類(lèi)和接口的共同子類(lèi) AbstractMessage am = (AbstractMessage) news; am.print(); } }
3.一個(gè)抽象類(lèi)可以使用implements實(shí)現(xiàn)多個(gè)接口,但是接口不能夠去繼承抽象類(lèi);
//因?yàn)榻涌诤皖?lèi)的定義命名要求相同,所以為了區(qū)分接口和類(lèi) //建議在所以的接口前面追加一個(gè)字母I interface INews{ public String get();//抽象方法 } //可以再類(lèi)上進(jìn)行明確描述,在以后的開(kāi)發(fā)之中也經(jīng)常出現(xiàn)以下的命名習(xí)慣 abstract class AbstractMessage implements INews{ //只有接口中的abstract中才可以省略,抽象類(lèi)中的不能省略 public abstract void print(); } class NewsImpl extends AbstractMessage{ public String get(){ return "www.baidu.com"; } public void print(){} //有方法體就叫覆寫(xiě) } /* 該類(lèi)的調(diào)用相當(dāng)于孫子實(shí)例化爺爺對(duì)象 將 爺爺對(duì)象轉(zhuǎn)換為兒子對(duì)象 */ public class InFa1{ public static void main(String args[]){ INews news = new NewsImpl(); System.out.println(news.get()); //NewsImpl是抽象類(lèi)和接口的共同子類(lèi) AbstractMessage am = (AbstractMessage) news; am.print(); } }
實(shí)際上此時(shí)關(guān)系屬于三層繼承。
接口與抽象類(lèi)
//因?yàn)榻涌诤皖?lèi)的定義命名要求相同,所以為了區(qū)分接口和類(lèi) //建議在所以的接口前面追加一個(gè)字母I interface INews{ public String get();//抽象方法 public void pirnt(); } //假設(shè)一個(gè)接口可能有無(wú)數(shù)個(gè)子類(lèi),但是對(duì)于一個(gè)方法的實(shí)現(xiàn)是一樣的 abstract class AbstractMessage implements INews{ public void print(){ System.out.println("www.baidu.com"); } } //生怕別人不知道NewsImpl是INews接口的子類(lèi),做一個(gè)重復(fù)標(biāo)記而已 class NewsImpl extends AbstractMessage implements INews{ public String get(){ return "www.baidu.com"; } public void print(){} //有方法體就叫覆寫(xiě) } /* 該類(lèi)的調(diào)用相當(dāng)于孫子實(shí)例化爺爺對(duì)象 將 爺爺對(duì)象轉(zhuǎn)換為兒子對(duì)象 */ public class InFa1{ public static void main(String args[]){ INews news = new NewsImpl(); System.out.println(news.get()); //NewsImpl是抽象類(lèi)和接口的共同子類(lèi) AbstractMessage am = (AbstractMessage) news; am.print(); } }
4.一個(gè)接口可以使用extends來(lái)繼承多個(gè)父接口。
interface A{ public void pirntA(); } interface B{ public void pirntB(); } interface C extends A,B{ public void pirntC(); } class Impl implements C{ public void pirntA(); public void pirntB(); public void pirntC(); } public class InFa1{ public static void main(String args[]){ } }
5.接口可以定義一系列的內(nèi)部接口,包括:內(nèi)部普通類(lèi)、內(nèi)部抽象類(lèi)、內(nèi)部接口,其中使用static定義的內(nèi)部接口就相當(dāng)于是一個(gè)外部接口
而在開(kāi)發(fā)之中,內(nèi)部類(lèi)是永遠(yuǎn)不會(huì)受到概念限制的,在一個(gè)類(lèi)中可以定義內(nèi)部類(lèi),在一個(gè)抽象類(lèi)之中也可以抽象內(nèi)部類(lèi),在一個(gè)接口里面也可以定義內(nèi)部抽象類(lèi)或內(nèi)部接口.但是從實(shí)際的開(kāi)發(fā)來(lái)講用戶(hù)去定義內(nèi)部抽象類(lèi)或內(nèi)部接口的時(shí)候是比較少見(jiàn)的(android開(kāi)發(fā)中見(jiàn)過(guò)),而且在定義內(nèi)部接口的時(shí)候如果使用了static,表示一個(gè)外部接口。
interface A{ public void printA(); static interface B{ //外部接口 public void printB(); } } class X implements A.B{ public void printA(){ System.out.println("A"); } public void printB(){ System.out.println("B"); } } public class Inter{ public static void main(String args[]){ A.B ab = new X(); ab.printB(); } }
3.3 使用接口定義標(biāo)準(zhǔn)
以上對(duì)于接口的概念并不是很難理解,但是需要強(qiáng)調(diào)的是,在實(shí)際開(kāi)發(fā)之中,接口有三大主要功能:
- 制定操作標(biāo)準(zhǔn);
- 表示一種能力;
- 將服務(wù)器端的遠(yuǎn)程方法試圖暴露給客戶(hù)端。
定義USB接口:
interface USB{ public void install(); //進(jìn)行安裝 public void work(); //進(jìn)行工作 }
定義USB的子類(lèi):
class Computer{ public void plugin(USB usb){ usb.install(); usb.work(); } } class Flash implements USB{ public void install(){ System.out.println("安裝U盤(pán)驅(qū)動(dòng)"); } public void work(){ System.out.println("U盤(pán)進(jìn)行工作"); } } class Printer implements USB{ public void install(){ System.out.println("安裝打印機(jī)驅(qū)動(dòng)"); } public void work(){ System.out.println("打印機(jī)進(jìn)行工作"); } }
源代碼:
interface USB{ public void install(); //進(jìn)行安裝 public void work(); //進(jìn)行工作 } class Computer{ public void plugin(USB usb){ usb.install(); usb.work(); } } class Flash implements USB{ public void install(){ System.out.println("安裝U盤(pán)驅(qū)動(dòng)"); } public void work(){ System.out.println("U盤(pán)進(jìn)行工作"); } } class Printer implements USB{ public void install(){ System.out.println("安裝打印機(jī)驅(qū)動(dòng)"); } public void work(){ System.out.println("打印機(jī)進(jìn)行工作"); } } public class InFa3{ public static void main(String args[]){ /* 安裝U盤(pán)驅(qū)動(dòng) U盤(pán)進(jìn)行工作 安裝打印機(jī)驅(qū)動(dòng) 打印機(jī)進(jìn)行工作 */ Computer cm = new Computer(); cm.plugin(new Flash()); cm.plugin(new Printer()); } }
發(fā)現(xiàn)使用接口和對(duì)象多態(tài)性結(jié)合,對(duì)于參數(shù)的統(tǒng)一更加明確。而且可以發(fā)現(xiàn)接口時(shí)再類(lèi)之上的設(shè)計(jì)。
3.4 抽象類(lèi)與接口的區(qū)別
區(qū)別 | 抽象類(lèi) | 接口 |
---|---|---|
定義關(guān)鍵字 | 使用abstract class進(jìn)行聲明 | 使用interface進(jìn)行聲明 |
組成 | 全局常量、全局變量、構(gòu)造方法、抽象方法、普通方法 | 全局變量、抽象方法 |
權(quán)限 | 可以使用任何權(quán)限 | 只能使用public權(quán)限 |
關(guān)系 | 一個(gè)抽象類(lèi)可以實(shí)現(xiàn)多個(gè)接口 | 接口不能繼承抽象類(lèi),卻可以繼承多個(gè)接口 |
使用 | 子類(lèi)使用extends | 子類(lèi)使用implements |
設(shè)計(jì)模式 | 模板設(shè)計(jì)模式 | 工廠模式、代理模式 |
局限 | 一個(gè)子類(lèi)只能繼承一個(gè)抽象方法 | 一個(gè)子類(lèi)可以實(shí)現(xiàn)多個(gè)接口 |
通過(guò)上面的分析可以得出結(jié)論:在開(kāi)發(fā)之中,抽象類(lèi)和接口實(shí)際上都是可以使用的,并且使用哪一個(gè)都沒(méi)有明確的限制,可是抽象類(lèi)有一個(gè)最大的缺點(diǎn)—一個(gè)子類(lèi)只能夠繼承一個(gè)抽象類(lèi),存在單繼承的局限,所以當(dāng)遇到抽象類(lèi)和接口都可以實(shí)現(xiàn)的情況下,優(yōu)先考慮接口,避免單繼承局限。
除了單繼承的局限之外,實(shí)際上使用抽象類(lèi)和接口都是類(lèi)似的,但是在實(shí)際的開(kāi)發(fā)中,抽象類(lèi)的設(shè)計(jì)比接口的復(fù)雜。
總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
深入淺析SPI機(jī)制在JDK與Spring?Boot中的應(yīng)用
SPI是一種使軟件框架或庫(kù)更加模塊化、可擴(kuò)展和可維護(hù)的有效方法。通過(guò)遵循“開(kāi)閉原則”,?SPI?確保了系統(tǒng)的穩(wěn)定性和靈活性,從而滿足了不斷變化的業(yè)務(wù)需求,這篇文章主要介紹了SPI機(jī)制在JDK與Spring?Boot中的應(yīng)用,需要的朋友可以參考下2023-09-09java創(chuàng)建多級(jí)目錄文件的實(shí)例講解
下面小編就為大家分享一篇java創(chuàng)建多級(jí)目錄文件的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01Springboot實(shí)現(xiàn)發(fā)送郵件及注冊(cè)激活步驟
為了方便郵件發(fā)送功能的使用,我們用郵件發(fā)送功能實(shí)現(xiàn)用戶(hù)注冊(cè),實(shí)現(xiàn)步驟大概就是進(jìn)行用戶(hù)注冊(cè)同時(shí)發(fā)送一封激活郵件,郵件里附帶激活鏈接,關(guān)于Springboot發(fā)送郵件注冊(cè)激活功能的實(shí)現(xiàn)參考下本文吧2021-06-06