????本文是我自己將來面試的筆記,整理的知識點(diǎn),也是為了防止忘記,尊重勞動成果,轉(zhuǎn)載注明出處哦!如果你也喜歡,那就點(diǎn)個小心心,文末贊賞一杯豆奶吧,嘻嘻。 讓我們共同成長吧……
第1章? JAVA基礎(chǔ)
本章內(nèi)容? ? java面試中常會被問到的基礎(chǔ)問題
1.面向?qū)ο蠛兔嫦蜻^程的區(qū)別
面向過程?:面向過程性能比面向?qū)ο蟾摺?/b>?因?yàn)轭愓{(diào)用時需要實(shí)例化,開銷比較大,比較消耗資源,所以當(dāng)性能是最重要的考量因素的時候,比如單片機(jī)、嵌入式開發(fā)、Linux/Unix等一般采用面向過程開發(fā)。但是,面向過程沒有面向?qū)ο笠拙S護(hù)、易復(fù)用、易擴(kuò)展。
面向?qū)ο?/b>?:面向?qū)ο笠拙S護(hù)、易復(fù)用、易擴(kuò)展。?因?yàn)槊嫦驅(qū)ο笥蟹庋b、繼承、多態(tài)性的特性,所以可以設(shè)計出低耦合的系統(tǒng),使系統(tǒng)更加靈活、更加易于維護(hù)。但是,面向?qū)ο笮阅鼙让嫦蜻^程低。
2.重載和重寫的區(qū)別
重載:?發(fā)生在同一個類中,方法名必須相同,參數(shù)類型不同、個數(shù)不同、順序不同,方法返回值和訪問修飾符可以不同,發(fā)生在編譯時。
重寫?:?發(fā)生在父子類中,方法名、參數(shù)列表必須相同,返回值范圍小于等于父類,拋出的異常范圍小于等于父類,訪問修飾符范圍大于等于父類;如果父類方法訪問修飾符為 private 則子類就不能重寫該方法。
3.JAVA面向?qū)ο蟮娜筇匦裕悍庋b,繼承,多態(tài)
封裝:把一個對象的屬性私有化,同時提供一些可以被外界訪問的屬性的方法,如果屬性不想被外界訪問,我們大可不必提供方法給外界訪問。但是如果一個類沒有提供給外界訪問的方法,那么這個類也沒有什么意義了。?
繼承: 繼承是使用已存在的類的定義作為基礎(chǔ)建立新類的技術(shù),新類的定義可以增加新的數(shù)據(jù)或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。通過使用繼承我們能夠非常方便地復(fù)用以前的代碼。
關(guān)于繼承如下 3 點(diǎn)請記?。?br>
????子類擁有父類對象所有的屬性和方法(包括私有屬性和私有方法),但是父類中的私有屬性和方法子類是無法訪問,只是擁有。
????子類可以擁有自己屬性和方法,即子類可以對父類進(jìn)行擴(kuò)展。
????子類可以用自己的方式實(shí)現(xiàn)父類的方法。(以后介紹)。
多態(tài):?所謂多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時并不確定,而是在程序運(yùn)行期間才確定,即一個引用變量到底會指向哪個類的實(shí)例對象,該引用變量發(fā)出的方法調(diào)用到底是哪個類中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定。
在Java中有兩種形式可以實(shí)現(xiàn)多態(tài):繼承(多個子類對同一方法的重寫)和接口(實(shí)現(xiàn)接口并覆蓋接口中同一方法)
4.StringBuffer和StringBuilder的區(qū)別?為什么String是final的
可變性
簡單的來說:String 類中使用 final 關(guān)鍵字修飾字符數(shù)組來保存字符串,private final char value[],所以 String 對象是不可變的。而StringBuilder 與 StringBuffer 都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中也是使用字符數(shù)組保存字符串char[]value?但是沒有用 final 關(guān)鍵字修飾,所以這兩種對象都是可變的。
StringBuilder 與 StringBuffer 的構(gòu)造方法都是調(diào)用父類構(gòu)造方法也就是 AbstractStringBuilder 實(shí)現(xiàn)的,大家可以自行查閱源碼。
、、、
public?static?void?main(String[] args){
}
、、、
線程安全性
String 中的對象是不可變的,也就可以理解為常量,線程安全。AbstractStringBuilder 是 StringBuilder 與 StringBuffer 的公共父類,定義了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 對方法加了同步鎖或者對調(diào)用的方法加了同步鎖,所以是線程安全的。StringBuilder 并沒有對方法進(jìn)行加同步鎖,所以是非線程安全的。
性能
每次對 String 類型進(jìn)行改變的時候,都會生成一個新的 String 對象,然后將指針指向新的 String 對象。StringBuffer 每次都會對 StringBuffer 對象本身進(jìn)行操作,而不是生成新的對象并改變對象引用。相同情況下使用 StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風(fēng)險。
對于三者使用的總結(jié):
操作少量的數(shù)據(jù): 適用String
單線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù): 適用StringBuilder
多線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù): 適用StringBuffer
5.Java的八種基本類型
整數(shù):byte,short,int,long
浮點(diǎn):float,double
字符:char
布爾:? boolean
6.接口和抽象類的區(qū)別
接口中所有的方法隱含的都是抽象的。而抽象類則可以同時包含抽象和非抽象的方法。
類可以實(shí)現(xiàn)很多個接口,但是只能繼承一個抽象類
類如果要實(shí)現(xiàn)一個接口,它必須要實(shí)現(xiàn)接口聲明的所有方法。但是,類可以不實(shí)現(xiàn)抽象類聲明的所有方法,當(dāng)然,在這種情況下,類也必須得聲明成是抽象的。
抽象類可以在不提供接口方法實(shí)現(xiàn)的情況下實(shí)現(xiàn)接口。
Java接口中聲明的變量默認(rèn)都是final的。抽象類可以包含非final的變量。
Java接口中的成員函數(shù)默認(rèn)是public的。抽象類的成員函數(shù)可以是private,protected或者是public。
接口是絕對抽象的,不可以被實(shí)例化。抽象類也不可以被實(shí)例化,但是,如果它包含main方法的話是可以被調(diào)用的。
7.==與equals的區(qū)別
==比較的是引用,比較的是引用的地址值 ,equals方法,是object中的方法,如果不進(jìn)行重寫的話,比較的也是引用的地址值,實(shí)際和==一樣。
.如果自己所寫的類中已經(jīng)重寫了equals方法,那么就安裝用戶自定義的方式來比較倆個對象是否相等,如果沒有重寫過equal方法,那么會調(diào)用父類(Object)中的equals方法進(jìn)行比較,也就是比較地址值。
8.hashcode()與equals()
equals(): 用來判斷兩個對象是否相同,再Object類中是通過判斷對象間的內(nèi)存地址來決定是否相同
hashCode(): 獲取哈希碼,也稱為散列碼,返回一個int整數(shù)。這個哈希碼的作用是確定該對象在哈希表中的索引位置。
9.序列化
?序列化的類要實(shí)現(xiàn)serializable接口
transient修飾符可以保證某個成員變量不被序列化
readObject和writeOject來實(shí)現(xiàn)實(shí)例的寫入和讀取。
事實(shí)上,一些擁有數(shù)組變量的類都會把數(shù)組設(shè)為transient修飾,這樣的話不會對整個數(shù)組進(jìn)行序列化,而是利用專門的方法將有數(shù)據(jù)的數(shù)組范圍進(jìn)行序列化,以便節(jié)省空間。
10.JAVA中的異常處理
Java異常類層次結(jié)構(gòu)圖

在 Java 中,所有的異常都有一個共同的祖先java.lang包中的?Throwable類。Throwable: 有兩個重要的子類:Exception(異常)?和?Error(錯誤)?,二者都是 Java 異常處理的重要子類,各自都包含大量子類。
Error(錯誤):是程序無法處理的錯誤,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問題。大多數(shù)錯誤與代碼編寫者執(zhí)行的操作無關(guān),而表示代碼運(yùn)行時 JVM(Java 虛擬機(jī))出現(xiàn)的問題。例如,Java虛擬機(jī)運(yùn)行錯誤(Virtual MachineError),當(dāng) JVM 不再有繼續(xù)執(zhí)行操作所需的內(nèi)存資源時,將出現(xiàn) OutOfMemoryError。這些異常發(fā)生時,Java虛擬機(jī)(JVM)一般會選擇線程終止。
這些錯誤表示故障發(fā)生于虛擬機(jī)自身、或者發(fā)生在虛擬機(jī)試圖執(zhí)行應(yīng)用時,如Java虛擬機(jī)運(yùn)行錯誤(Virtual MachineError)、類定義錯誤(NoClassDefFoundError)等。這些錯誤是不可查的,因?yàn)樗鼈冊趹?yīng)用程序的控制和處理能力之 外,而且絕大多數(shù)是程序運(yùn)行時不允許出現(xiàn)的狀況。對于設(shè)計合理的應(yīng)用程序來說,即使確實(shí)發(fā)生了錯誤,本質(zhì)上也不應(yīng)該試圖去處理它所引起的異常狀況。在 Java中,錯誤通過Error的子類描述。
Exception(異常):是程序本身可以處理的異常。Exception 類有一個重要的子類?RuntimeException。RuntimeException 異常由Java虛擬機(jī)拋出。NullPointerException(要訪問的變量沒有引用任何對象時,拋出該異常)、ArithmeticException(算術(shù)運(yùn)算異常,一個整數(shù)除以0時,拋出該異常)和?ArrayIndexOutOfBoundsException?(下標(biāo)越界異常)。
注意:異常和錯誤的區(qū)別:異常能被程序本身處理,錯誤是無法處理。
Throwable類常用的方法
public string getMessage():返回異常發(fā)生時的簡要描述
public string toString():返回異常發(fā)生時的詳細(xì)信息
public string getLocalizedMessage():返回異常對象的本地化信息。使用Throwable的子類覆蓋這個方法,可以生成本地化信息。如果子類沒有覆蓋該方法,則該方法返回的信息與getMessage()返回的結(jié)果相同
public void printStackTrace():在控制臺上打印Throwable對象封裝的異常信息
異常處理總結(jié)
try 塊:?用于捕獲異常。其后可接零個或多個catch塊,如果沒有catch塊,則必須跟一個finally塊。
catch 塊:?用于處理try捕獲到的異常。
finally 塊:?無論是否捕獲或處理異常,finally塊里的語句都會被執(zhí)行。當(dāng)在try塊或catch塊中遇到return 語句時,finally語句塊將在方法返回之前被執(zhí)行。
在以下4種特殊情況下,finally塊不會被執(zhí)行:
在finally語句塊第一行發(fā)生了異常。 因?yàn)樵谄渌?,finally塊還是會得到執(zhí)行
在前面的代碼中用了System.exit(int)已退出程序。 exit是帶參函數(shù) ;若該語句在異常語句之后,finally會執(zhí)行
程序所在的線程死亡。
關(guān)閉CPU。
11.反射
1 Java反射包reflection提供對Class,Method,field,constructor1 等信息的封裝類型。
2 通過這些api可以輕易獲得一個類的各種信息并且可以進(jìn)行實(shí)例化,方法調(diào)用等。
類中的private參數(shù)可以通過setaccessible方法強(qiáng)制獲取。
3 反射的作用可謂是博大精深,JDK動態(tài)代理生成代理類的字節(jié)碼后,首先把這個類通過defineclass定義成一個類,然后用class.for(name)會把該類加載到j(luò)vm,之后我們就可以通過,A.class.GetMethod()獲取其方法,然后通過invoke調(diào)用其方法,在調(diào)用這個方法時,實(shí)際上會通過被代理類的引用再去調(diào)用原方法。
12.動態(tài)代理
1 jdk自帶的動態(tài)代理可以代理一個已經(jīng)實(shí)現(xiàn)接口的類。
2 cglib代理可以代理一個普通的類。
3 動態(tài)代理的基本實(shí)現(xiàn)原理都是通過字節(jié)碼框架動態(tài)生成字節(jié)碼,并且在用defineclass加載類后,獲取代理類的實(shí)例。
一般需要實(shí)現(xiàn)一個代理處理器,用來處理被代理類的前置操作和后置操作。在JDK動態(tài)代理中,這個類叫做invocationHandler。
4 JDK動態(tài)代理首先獲取被代理類的方法,并且只獲取在接口中聲明的方法,生成代理類的字節(jié)碼后,首先把這個類通過defineclass定義成一個類,然后把該類加載到j(luò)vm,之后我們就可以通過,A.class.GetMethod()獲取其方法,然后通過invoke調(diào)用其方法,在調(diào)用這個方法時,實(shí)際上會通過被代理類的引用再去調(diào)用原方法。
5 而對于cglib動態(tài)代理,一般會把被代理類設(shè)為代理類的父類,然后獲取被代理類中所有非final的方法,通過asm字節(jié)碼框架生成代理類的字節(jié)碼,這個代理類很神奇,他會保留原來的方法以及代理后的方法,通過方法數(shù)組的形式保存。
cglib的動態(tài)代理需要實(shí)現(xiàn)一個enhancer和一個interceptor,在interceptor中配置我們需要的代理內(nèi)容。如果沒有配置interceptor,那么代理類會調(diào)用被代理類自己的方法,如果配置了interceptor,則會使用代理類修飾過的方法。