Java常見面試題匯總-----------Java基礎(chǔ)(抽象類和接口、構(gòu)造方法、內(nèi)部類、枚舉類)

7. 抽象類和接口的比較

??1、什么是抽象類? 就是對類更高的抽象。抽象類作為多個(gè)子類的共同父類。它所體現(xiàn)的是一種模版設(shè)計(jì),抽象類作為多個(gè)子類的父類,可以把它理解為系統(tǒng)實(shí)現(xiàn)過程中的中間產(chǎn)品,這個(gè)中間產(chǎn)品已經(jīng)實(shí)現(xiàn)了系統(tǒng)的部分功能,但是不能當(dāng)成最終產(chǎn)品,還需要進(jìn)一步的完善。
??當(dāng)父類的一些方法不能確定時(shí),可以用abstract關(guān)鍵字來修飾該方法【抽象方法】,用abstract來修飾該類【抽象類】。
??1)、抽象類不能被實(shí)例化。
??2)、用abstract關(guān)鍵字來修飾一個(gè)方法時(shí),這個(gè)方法就是抽象方法,抽象方法不能有主體【即不能實(shí)現(xiàn)】;用abstract關(guān)鍵字來修飾一個(gè)類時(shí),這個(gè)類就叫抽象類。
??3)、抽象類不一定要包含abstract方法。也就是說抽象類可以沒有abstract方法;但是一旦類包含了abstract方法,則這個(gè)類必須聲明為abstract。

??2、什么是接口? 接口是一種規(guī)范,就像現(xiàn)實(shí)中生產(chǎn)主板和內(nèi)存條或者網(wǎng)卡的不是同一家產(chǎn)商,但是為何內(nèi)存或者網(wǎng)卡插入到主板上就能用呢,因?yàn)樗麄兌甲袷亓四撤N規(guī)范。然后就可以使用。雖然他們的內(nèi)部實(shí)現(xiàn)可能完全不同。就好比在java語言中的方法內(nèi)部實(shí)現(xiàn)你不需要關(guān)心,只需要知道這個(gè)接口是怎樣的干嘛的就行了,直接用。既然是一種規(guī)范,那他在編程語言中就能在架構(gòu)中起到非常之大的作用,在一個(gè)應(yīng)用程序之間的時(shí)候,接口體現(xiàn)的是一耦合標(biāo)準(zhǔn)。特別是在多個(gè)應(yīng)用程序需要對接的時(shí)候。接口是多個(gè)應(yīng)用程序的通信標(biāo)準(zhǔn)。接口就是給出一些沒有內(nèi)容的方法,封裝在一起,到某個(gè)類要使用的時(shí)候,再根據(jù)具體情況把這些方法寫出來。
??接口是更加抽象的抽象的類,抽象類里的方法(非抽象方法,抽象類可以有非抽象方法)可以有方法體,接口里的所有方法都沒有方法體。接口體現(xiàn)了程序設(shè)計(jì)的多態(tài)和高內(nèi)聚低偶和的設(shè)計(jì)思想。
??1)、接口中的所有方法都不能有主體,不能被實(shí)例化。
??2)、一個(gè)類可以實(shí)現(xiàn)多個(gè)接口。
??3)、接口中可以有變量【但變量不能用private和protected修飾】。a、Java接口中的變量是公共的(public),靜態(tài)的(static),最終的常量(final),相當(dāng)于全局常量,所以定義接口變量時(shí)必須初始化。 b、接口中的變量,本質(zhì)上都是static的,不管你加不加static修飾。c、在java開發(fā)中,我們經(jīng)常用的變量,定義在接口中,作為全局變量使用。訪問形式:接口名.變量名。
??4)、一個(gè)接口不能繼承其它的類,但是可以繼承別的接口。
??5)、接口沒有方法就可以作為一個(gè)標(biāo)志,比如可序列化的接口Serializable,沒有方法的接口稱為空接口。

7.1. 抽象類與接口的比較

??接口和抽象類都不能實(shí)例化,他們都位于繼承樹的頂端,用于被其他類實(shí)現(xiàn)和繼承。接口和抽象類都可以包含抽象方法,實(shí)現(xiàn)接口或繼承抽象類的普通子類都必須實(shí)現(xiàn)這些抽象方法。
??他們的區(qū)別:
??1、屬性:接口沒有普通屬性,只有靜態(tài)屬性,并且只能用public final static 修飾(并且是默認(rèn)的,就算你在接口中定義Int i = 0 它也會(huì)被隱式的加上public final static);而抽象類可以有普通屬性,可以有靜態(tài)屬性(類屬性)。
??2、方法:接口中的方法都沒有方法體并且都是默認(rèn)使用public abstracrt 修飾,不能定義靜態(tài)方法。 而抽象類可以有普通方法,也可以沒有抽象方法,也可以定義靜態(tài)方法。
??3、構(gòu)造函數(shù):接口中沒有構(gòu)造器,抽象類中可以有構(gòu)造器, 但是它不能用于new 對象 而是用于子類調(diào)用來初始化抽象類的操作。
??4、初始化塊:接口中不能包含初始化塊,而抽象方法中可以包含初始化塊。
??5、一個(gè)類只能有一個(gè)直接父類,包括抽象類,而類可以實(shí)現(xiàn)多個(gè)接口,彌補(bǔ)了java不能多繼承的不足。

7.2.新版本中的修改

??1、JDK1.8以前,抽象類中的方法默認(rèn)訪問權(quán)限protected,JDK1.8時(shí)默認(rèn)訪問權(quán)限default。
??2、JDK1.8接口,增加了default和static方法,這2個(gè)都可以有方法體的,default方法屬于實(shí)例,static方法屬于類(接口),接口的靜態(tài)方法不會(huì)被繼承,靜態(tài)變量會(huì)被繼承。
??3、JDK1.8,如果接口只有一個(gè)抽象方法自動(dòng)變成函數(shù)式接口,可以用使用@FunctionInterface注解,接口有FunctionInterface注解只能有一個(gè)抽象方法。
??4、從java8開始接口里可以有靜態(tài)方式,用static修飾,但是接口里的靜態(tài)方法的修飾符只能是public,且默認(rèn)是public。調(diào)用時(shí)(接口名.方法名)。
??5、java8里,除了可以在接口里寫靜態(tài)方法,還可以寫非靜態(tài)方法,但是必須用default修飾,且只能是public,默認(rèn)也是public。

8. 構(gòu)造方法,構(gòu)造方法重載,什么是復(fù)制構(gòu)造方法?

??構(gòu)造方法是類的一種特殊方法,它的主要作用是完成對新對象的<font color="red">初始化。</font>
??1、方法名和類名相同,沒有返回值。
??2、在創(chuàng)建(new)一個(gè)類的新對象時(shí),系統(tǒng)會(huì)自動(dòng)的調(diào)用該類的構(gòu)造方法完成對新對象的初始化。
??3、普通方法可以和類名相同,和構(gòu)造方法唯一的區(qū)別在于,構(gòu)造方法沒有返回值(注意是沒有不是void)。
??4、定義類的時(shí)候,若沒有自定義構(gòu)造方法,則會(huì)有一個(gè)默認(rèn)的無參構(gòu)造方法,若自定義了構(gòu)造方法,則沒有無參構(gòu)造方法。
??5、構(gòu)造方法不能被繼承,構(gòu)造方法只能被顯式或者隱式地調(diào)用。
??6、子類的構(gòu)造方法總是先調(diào)用父類的構(gòu)造方法,如果子類的構(gòu)造方法沒有顯式地指出使用父類的哪個(gè)構(gòu)造方法,子類則默認(rèn)調(diào)用父類的無參構(gòu)造方法(此時(shí)若父類自定義了構(gòu)造方法,而子類又沒有用super則會(huì)報(bào)錯(cuò))。
??7、Java不支持像C++中那樣的復(fù)制構(gòu)造方法(沒有這個(gè)概念),但是在Object類中有一個(gè)clone()方法。
??Protected Object clone() throws CloneNotSupportedException:創(chuàng)建并返回此對象的一個(gè)副本。“副本”的準(zhǔn)確含義可能依賴于對象的類。
??這樣做的目的是,對于任何對象 x,表達(dá)式:x.clone() != x為true,表達(dá)式:x.clone().getClass() == x.getClass()也為true,但這些并非必須要滿足的要求。一般情況下:x.clone().equals(x)為true,但這并非必須要滿足的要求。
??首先,使用這個(gè)方法的類必須實(shí)現(xiàn)java.lang.Cloneable接口,否則會(huì)拋出CloneNotSupportedException異常。Cloneable接口中不包含任何方法,所以實(shí)現(xiàn)它時(shí)只要在類聲明中加上implements語句即可。
??第二個(gè)比較特殊的地方在于這個(gè)方法是protected修飾的,覆寫clone()方法的時(shí)候需要寫成public,才能讓類外部的代碼調(diào)用。
??按照慣例,返回的對象應(yīng)該通過調(diào)用super.clone獲得。如果一個(gè)類及其所有的超類(Object除外)都遵守此約定,則 x.clone().getClass() == x.getClass()。
??按照慣例,此方法返回的對象應(yīng)該獨(dú)立于該對象(正被復(fù)制的對象)。要獲得此獨(dú)立性,在super.clone返回對象之前,有必要對該對象的一個(gè)或多個(gè)字段進(jìn)行修改。這通常意味著要復(fù)制包含正在被復(fù)制對象的內(nèi)部“深層結(jié)構(gòu)”的所有可變對象,并使用對副本的引用替換對這些對象的引用。如果一個(gè)類只包含基本字段或?qū)Σ蛔儗ο蟮囊茫敲赐ǔ2恍枰薷?super.clone 返回的對象中的字段。
??也就是clone的淺拷貝和深拷貝問題,在具體使用的時(shí)候需要特別注意:
??淺拷貝:如果一個(gè)對象內(nèi)部還有一個(gè)引用類型的基本變量,那么在拷貝該對象的時(shí)候,只是在通過clone方法新產(chǎn)生的新對象中拷貝一個(gè)該基本類型的引用。換句話說,也就是新對象和原對象他們內(nèi)部都含有一個(gè)指向同一對象的引用。
??深拷貝:拷貝對象的時(shí)候,如果對象內(nèi)部含有一個(gè)引用類型的變量,那么就會(huì)再將該引用類型的變量指向的對象復(fù)制一份,然后引用該新對象。
??8、實(shí)際上,特別需要注意的一點(diǎn)是,Java對象并不是由構(gòu)造器創(chuàng)建的,而是由new運(yùn)算符創(chuàng)建的,在程序運(yùn)行時(shí),是new運(yùn)算符在堆上開辟一塊空間,然后執(zhí)行對象的初始化(其中包括調(diào)用構(gòu)造器),當(dāng)對象創(chuàng)建成功,也是new運(yùn)算符將對象的起始地址返回給應(yīng)用程序的(并非構(gòu)造器)。實(shí)際上構(gòu)造器的作用是在對象創(chuàng)建的時(shí)候進(jìn)行類中成員變量的初始化,而絕非創(chuàng)建對象,構(gòu)造器也沒有返回值。因此程序執(zhí)行的順序是,先創(chuàng)建對象,然后求解構(gòu)造器所有形參表達(dá)式的值(若形參表達(dá)式的計(jì)算出現(xiàn)異常,則不會(huì)調(diào)用構(gòu)造器方法),最后調(diào)用構(gòu)造器對對象進(jìn)行初始化。

9. Java內(nèi)部類

??內(nèi)部類(inner class)是定義在另一個(gè)類內(nèi)部的類。
??使用內(nèi)部類的原因有三個(gè):
??1)、內(nèi)部類方法可以訪問該類定義所在的作用域中的數(shù)據(jù),包括私有數(shù)據(jù)。
??2)、內(nèi)部類能夠隱藏起來,不被同一個(gè)包中的其他的類所見。
??3)、想要定義一個(gè)回調(diào)函數(shù),且不想編寫大量代碼時(shí),使用匿名內(nèi)部類比較便捷。
??4)、內(nèi)部類有四種:成員內(nèi)部類、局部內(nèi)部類、靜態(tài)內(nèi)部類、匿名內(nèi)部類

9.1、成員內(nèi)部類

??成員內(nèi)部類也是最普通的內(nèi)部類,它是外圍類的一個(gè)成員,所以他是可以無限制的訪問外圍類的所有成員屬性和方法,盡管是private的,但是外圍類要訪問內(nèi)部類的成員屬性和方法則需要通過內(nèi)部類實(shí)例來訪問。如果在內(nèi)部類中定義有和外部類同名的實(shí)例變量,訪問:OuterClass.this.outerMember;
??在成員內(nèi)部類中要注意兩點(diǎn),第一:成員內(nèi)部類中不能存在任何static的變量和方法(因?yàn)樾枰葎?chuàng)建外部類,才能創(chuàng)建自己,可以聲明static的常量);第二:成員內(nèi)部類是依附于外圍類的,所以只有先創(chuàng)建了外圍類才能夠創(chuàng)建內(nèi)部類。

9.2、局部內(nèi)部類

??局部內(nèi)部類,它是嵌套在方法和作用域內(nèi)的,對于這個(gè)類的使用主要是應(yīng)用與解決比較復(fù)雜的問題,想創(chuàng)建一個(gè)類來輔助我們的解決方案,但又不希望這個(gè)類是公共可用的,所以就產(chǎn)生了局部內(nèi)部類,局部內(nèi)部類和成員內(nèi)部類一樣被編譯,只是它的作用域發(fā)生了改變,它只能在該方法和屬性中被使用,出了該方法和屬性就會(huì)失效。
??局部內(nèi)部類可以訪問的外部類的成員根據(jù)所在方法體不同。如果在靜態(tài)方法中:可以訪問外部類中所有靜態(tài)成員,包含私有;如果在實(shí)例方法中:可以訪問外部類中所有的成員,包含私有。局部內(nèi)部類可以訪問所在方法中定義的局部變量,但是要求局部變量必須使用final修飾。

9.3、匿名內(nèi)部類

??1、匿名內(nèi)部類是沒有訪問修飾符的,也是唯一一種沒有構(gòu)造方法的類。
??2、new 匿名內(nèi)部類,這個(gè)類首先是要存在的。
??3、注意當(dāng)所在方法的形參需要被匿名內(nèi)部類使用,那么這個(gè)形參就必須為final。

9.4、靜態(tài)內(nèi)部類(靜態(tài)嵌套類)

??使用static修飾的內(nèi)部類我們稱之為靜態(tài)內(nèi)部類,或者稱之為嵌套內(nèi)部類。靜態(tài)內(nèi)部類與非靜態(tài)內(nèi)部類之間存在一個(gè)最大的區(qū)別,我們知道非靜態(tài)內(nèi)部類在編譯完成之后會(huì)隱含地保存著一個(gè)引用,該引用是指向創(chuàng)建它的外圍類,但是靜態(tài)內(nèi)部類卻沒有。沒有這個(gè)引用就意味著:
??1、它的創(chuàng)建是不需要依賴于外圍類的。
??2、它不能使用任何外圍類的非static成員變量和方法。

10. 枚舉類

??(1)、定義一個(gè)枚舉類,使用的是enum關(guān)鍵字而不是class。
??(2)、枚舉類的實(shí)例一定是有限多個(gè)(可枚舉的),所有的enum變量必須定義在枚舉類的第一行,用逗號隔開,定義完所有的變量后,以分號結(jié)束,如果只有枚舉變量,而沒有自定義變量,分號可以省略。枚舉變量最好大寫,在其他類中使用enum變量的時(shí)候,只需要【類名.變量名】就可以了,和使用靜態(tài)變量一樣。
??Enum變量默認(rèn)添加public static final修飾。
??(3)enum類可以把它看成一個(gè)普通類,可以有構(gòu)造器,成員方法,成員變量。當(dāng)然和普通類也有一定的區(qū)別:
??枚舉類的構(gòu)造方法默認(rèn)使用private修飾,且只能使用private修飾;
??枚舉類默認(rèn)繼承自Enum類,所以不能繼承其他類,Enum類實(shí)現(xiàn)了Serializable、Comparable接口;
??枚舉類默認(rèn)使用final修飾,因此不能派生子類。如果需要擴(kuò)展enum中的元素,在一個(gè)接口的內(nèi)部,創(chuàng)建實(shí)現(xiàn)該接口的枚舉,以此將元素進(jìn)行分組。達(dá)到將枚舉元素進(jìn)行分組的目的。
??(4)、switch()參數(shù)可以使用enum
??(5)、enum允許程序員為eunm實(shí)例編寫方法。所以可以為每個(gè)enum實(shí)例賦予各自不同的行為。
??(6)、常用方法

10.1、枚舉類方法:

??valueOf()方法:它的作用是傳來一個(gè)字符串,然后將它轉(zhuǎn)變?yōu)閷?yīng)的枚舉變量。前提是你傳的字符串和定義枚舉變量的字符串一模一樣,區(qū)分大小寫。如果你傳了一個(gè)不存在的字符串,那么會(huì)拋出異常。
??values()方法:這個(gè)方法會(huì)返回包括所有枚舉變量的數(shù)組,可以方便的用來做循環(huán)。
??name()方法:它和toString()方法的返回值一樣,這兩個(gè)方法的默認(rèn)實(shí)現(xiàn)是一樣的,唯一的區(qū)別是,你可以重寫toString方法。name變量就是枚舉變量的字符串形式。

10.2、枚舉變量方法:

??toString()方法:該方法直接返回枚舉定義枚舉變量的字符串。
??ordinal()方法:默認(rèn)情況下,枚舉類會(huì)給所有的枚舉變量一個(gè)默認(rèn)的次序,該次序從0開始,類似于數(shù)組的下標(biāo)。而.ordinal()方法就是獲取這個(gè)次序(或者說下標(biāo))。枚舉類中枚舉變量的次序可以自定義。
??compareTo()方法(枚舉類實(shí)現(xiàn)了Comparable接口):該方法用來比較兩個(gè)枚舉變量的”大小”,實(shí)際上比較的是兩個(gè)枚舉變量的次序,返回兩個(gè)次序相減后的結(jié)果,如果為負(fù)數(shù),就證明變量1”小于”變量2 (變量1.compareTo(變量2),返回【變量1.ordinal()- 變量2.ordinal()】)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,998評論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內(nèi)容