【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】01.Java基礎(chǔ)問(wèn)題_第1頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】01.Java基礎(chǔ)問(wèn)題_第2頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】01.Java基礎(chǔ)問(wèn)題_第3頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】01.Java基礎(chǔ)問(wèn)題_第4頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】01.Java基礎(chǔ)問(wèn)題_第5頁(yè)
已閱讀5頁(yè),還剩10頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】01.Java基礎(chǔ)問(wèn)題

目錄介紹請(qǐng)手寫(xiě)equal方法,講講具體的原理?請(qǐng)說(shuō)下String與StringBuffer區(qū)別,StringBuffer底部如何實(shí)現(xiàn)?String類可以被繼承嗎,為什么?Stringa=""和Stringa=newString("")的的關(guān)系和異同?String的創(chuàng)建機(jī)制?static關(guān)鍵字可以修飾什么?static使用的注意事項(xiàng)有哪些?static關(guān)鍵字的特點(diǎn)?為什么Java中的String是不可變的(Immutable)?字符串設(shè)計(jì)和實(shí)現(xiàn)考量?String不可變的好處?Hashcode與equal區(qū)別,什么時(shí)候需要用到hashcode?講講里面的原理。如何解決Hash沖突?訪問(wèn)修飾符public,private,protected,以及不寫(xiě)(默認(rèn))時(shí)的區(qū)別?靜態(tài)變量和實(shí)例變量的區(qū)別?成員變量與局部變量的區(qū)別有那些?如何實(shí)現(xiàn)對(duì)象克?。可羁寺?,淺克隆分別說(shuō)的是什么意思?int和Integer的區(qū)別?裝箱、拆箱什么含義?什么時(shí)候裝箱/拆箱?裝箱和拆箱是如何實(shí)現(xiàn)的?Object有哪些公有方法?final,finally,finalize有什么不同?finally什么情況下不會(huì)被執(zhí)行?為什么要使用通配符?上界通配符和下界通配符如何理解和注意要點(diǎn)?什么是×××通配符?什么是泛型擦除,能否通過(guò)開(kāi)發(fā)中實(shí)際案例說(shuō)下?如何獲取泛型的具體的類型【反射】?如何驗(yàn)證int類型是否線程安全?那些類型是線程安全的?舉一個(gè)線程安全的例子【AtomicInteger】?Java序列話中如果有些字段不想進(jìn)行序列化怎么辦?有沒(méi)有可能兩個(gè)不相等的對(duì)象有相同的hashcode?當(dāng)兩個(gè)對(duì)象hashcode相同怎么辦?如何獲取值對(duì)象?原始數(shù)據(jù)類型和引用類型局限性?為何要引用基本數(shù)據(jù)包裝類?newInteger(123)與Integer.valueOf(123)有何區(qū)別,請(qǐng)從底層實(shí)現(xiàn)分析兩者區(qū)別?好消息博客筆記大匯總【15年10月到至今】,包括Java基礎(chǔ)及深入知識(shí)點(diǎn),Android技術(shù)博客,Python學(xué)習(xí)筆記等等,還包括平時(shí)開(kāi)發(fā)中遇到的bug匯總,當(dāng)然也在工作之余收集了大量的面試題,長(zhǎng)期更新維護(hù)并且修正,持續(xù)完善……開(kāi)源的文件是markdown格式的!同時(shí)也開(kāi)源了生活博客,從12年起,積累共計(jì)500篇[近100萬(wàn)字],將會(huì)陸續(xù)發(fā)表到網(wǎng)上,轉(zhuǎn)載請(qǐng)注明出處,謝謝!鏈接地址:/yangchong211/YCBlogs如果覺(jué)得好,可以star一下,謝謝!當(dāng)然也歡迎提出建議,萬(wàn)事起于忽微,量變引起質(zhì)變!所有博客將陸續(xù)開(kāi)源到GitHub!請(qǐng)手寫(xiě)equal方法,講講具體的原理?代碼如下所示,如果是手寫(xiě)代碼,一定要弄清楚邏輯思路!publicbooleanequals(ObjectanObject){if(this==anObject){returntrue;}if(anObjectinstanceofString){StringanotherString=(String)anObject;intn=count;if(n==anotherString.count){inti=0;while(n--!=0){if(charAt(i)!=anotherString.charAt(i))returnfalse;i++;}returntrue;}}returnfalse;}請(qǐng)說(shuō)下String與StringBuffer區(qū)別,StringBuffer底部如何實(shí)現(xiàn)?String類可以被繼承嗎,為什么?String類的特點(diǎn)String的特點(diǎn)是一旦被創(chuàng)建,就不能被改變。注意是地址不能改變。StringBuffer底層是可變的字節(jié)序列……String類可以被繼承嗎看String源碼可知,String類被final關(guān)鍵字修飾了,所以不能被繼承。這個(gè)地方可以說(shuō)下final關(guān)鍵字作用。String、StringBuffer和StringBuilder的區(qū)別?String是字符串常量,而StringBuffer、StringBuilder都是字符串變量,即String對(duì)象一創(chuàng)建后不可更改,而后兩者的對(duì)象是可更改的:StringBuffer是線程安全的,而StringBuilder是非線程安全的,這是由于StringBuffer對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖String更適用于少量的字符串操作的情況,StringBuilder適用于單線程下在字符緩沖區(qū)進(jìn)行大量操作的情況,StringBuffer適用于多線程下在字符緩沖區(qū)進(jìn)行大量操作的情況技術(shù)博客大總結(jié)Stringa=""和Stringa=newString("")的的關(guān)系和異同?String的創(chuàng)建機(jī)制?區(qū)別通過(guò)Stringa=""直接賦值的方式得到的是一個(gè)字符串常量,存在于常量池;注意,相同內(nèi)容的字符串在常量池中只有一個(gè),即如果池已包含內(nèi)容相等的字符串會(huì)返回池中的字符串,反之會(huì)將該字符串放入池中通過(guò)newString("")創(chuàng)建的字符串不是常量是實(shí)例對(duì)象,會(huì)在堆內(nèi)存開(kāi)辟空間并存放數(shù)據(jù),且每個(gè)實(shí)例對(duì)象都有自己的地址空間String的創(chuàng)建機(jī)制由于String在Java世界中使用過(guò)于頻繁,Java為了避免在一個(gè)系統(tǒng)中產(chǎn)生大量的String對(duì)象,引入了字符串常量池。其運(yùn)行機(jī)制是:創(chuàng)建一個(gè)字符串時(shí),首先檢查池中是否有值相同的字符串對(duì)象,如果有則不需要?jiǎng)?chuàng)建直接從池中剛查找到的對(duì)象引用;如果沒(méi)有則新建字符串對(duì)象,返回對(duì)象引用,并且將新創(chuàng)建的對(duì)象放入池中。但是,通過(guò)new方法創(chuàng)建的String對(duì)象是不檢查字符串池的,而是直接在堆區(qū)或棧區(qū)創(chuàng)建一個(gè)新的對(duì)象,也不會(huì)把對(duì)象放入池中。上述原則只適用于通過(guò)直接量給String對(duì)象引用賦值的情況。static關(guān)鍵字可以修飾什么?static使用的注意事項(xiàng)有哪些?static關(guān)鍵字的特點(diǎn)?可以用來(lái)修飾:成員變量,成員方法,代碼塊,內(nèi)部類等。具體如下所示修飾成員變量和成員方法被static修飾的成員屬于類,不屬于單個(gè)這個(gè)類的某個(gè)對(duì)象,被類中所有對(duì)象共享,可以并且建議通過(guò)類名調(diào)用。被static聲明的成員變量屬于靜態(tài)成員變量,靜態(tài)變量存放在Java內(nèi)存區(qū)域的方法區(qū)。靜態(tài)代碼塊靜態(tài)代碼塊定義在類中方法外,靜態(tài)代碼塊在非靜態(tài)代碼塊之前執(zhí)行(靜態(tài)代碼塊—>非靜態(tài)代碼塊—>構(gòu)造方法)該類不管創(chuàng)建多少對(duì)象,靜態(tài)代碼塊只執(zhí)行一次.靜態(tài)內(nèi)部類(static修飾類的話只能修飾內(nèi)部類)靜態(tài)內(nèi)部類與非靜態(tài)內(nèi)部類之間存在一個(gè)最大的區(qū)別:非靜態(tài)內(nèi)部類在編譯完成之后會(huì)隱含地保存著一個(gè)引用,該引用是指向創(chuàng)建它的外圍內(nèi),但是靜態(tài)內(nèi)部類卻沒(méi)有。沒(méi)有這個(gè)引用就意味著:1.它的創(chuàng)建是不需要依賴外圍類的創(chuàng)建。2.它不能使用任何外圍類的非static成員變量和方法。靜態(tài)導(dǎo)包(用來(lái)導(dǎo)入類中的靜態(tài)資源,1.5之后的新特性):這兩個(gè)關(guān)鍵字連用可以指定導(dǎo)入某個(gè)類中的指定靜態(tài)資源,并且不需要使用類名調(diào)用類中靜態(tài)成員,可以直接使用類中靜態(tài)成員變量和成員方法。static使用的注意事項(xiàng)有哪些?在靜態(tài)方法中是沒(méi)有this關(guān)鍵字的靜態(tài)是隨著類的加載而加載,this是隨著對(duì)象的創(chuàng)建而存在。靜態(tài)比對(duì)象先存在。靜態(tài)方法只能訪問(wèn)靜態(tài)的成員變量和靜態(tài)的成員方法【靜態(tài)只能訪問(wèn)靜態(tài),非靜態(tài)可以訪問(wèn)靜態(tài)的也可以訪問(wèn)非靜態(tài)的】static關(guān)鍵字的特點(diǎn)?隨著類的加載而加載優(yōu)先于對(duì)象存在被類的所有對(duì)象共享可以通過(guò)類名調(diào)用【靜態(tài)修飾的內(nèi)容一般我們稱其為:與類相關(guān)的,類成員】為什么Java中的String是不可變的(Immutable)?字符串設(shè)計(jì)和實(shí)現(xiàn)考量?String不可變的好處?不可變類String的原因String主要的三個(gè)成員變量charvalue[],intoffset,intcount均是private,final的,并且沒(méi)有對(duì)應(yīng)的getter/setter;String對(duì)象一旦初始化完成,上述三個(gè)成員變量就不可修改;并且其所提供的接口任何對(duì)這些域的修改都將返回一個(gè)新對(duì)象;技術(shù)博客大總結(jié)是典型的Immutable類,被聲明成為finalclass,所有屬性也都是final的。也由于它的不可變,類似拼接、裁剪字符串等動(dòng)作,都會(huì)產(chǎn)生新的String對(duì)象。字符串設(shè)計(jì)和實(shí)現(xiàn)考量?String是Immutable類的典型實(shí)現(xiàn),原生的保證了基礎(chǔ)線程安全,因?yàn)槟銦o(wú)法對(duì)它內(nèi)部數(shù)據(jù)進(jìn)行任何修改,這種便利甚至體現(xiàn)在拷貝構(gòu)造函數(shù)中,由于不可變,Immutable對(duì)象在拷貝時(shí)不需要額外復(fù)制數(shù)據(jù)。為了實(shí)現(xiàn)修改字符序列的目的,StringBuffer和StringBuilder底層都是利用可修改的(char,JDK9以后是byte)數(shù)組,二者都繼承了AbstractStringBuilder,里面包含了基本操作,區(qū)別僅在于最終的方法是否加了synchronized。這個(gè)內(nèi)部數(shù)組應(yīng)該創(chuàng)建成多大的呢?如果太小,拼接的時(shí)候可能要重新創(chuàng)建足夠大的數(shù)組;如果太大,又會(huì)浪費(fèi)空間。目前的實(shí)現(xiàn)是,構(gòu)建時(shí)初始字符串長(zhǎng)度加16(這意味著,如果沒(méi)有構(gòu)建對(duì)象時(shí)輸入最初的字符串,那么初始值就是16)。我們?nèi)绻_定拼接會(huì)發(fā)生非常多次,而且大概是可預(yù)計(jì)的,那么就可以指定合適的大小,避免很多次擴(kuò)容的開(kāi)銷。擴(kuò)容會(huì)產(chǎn)生多重開(kāi)銷,因?yàn)橐獟仐壴袛?shù)組,創(chuàng)建新的(可以簡(jiǎn)單認(rèn)為是倍數(shù))數(shù)組,還要進(jìn)行arraycopy。String不可變的好處?可以緩存hash值因?yàn)镾tring的hash值經(jīng)常被使用,例如String用做HashMap的key。不可變的特性可以使得hash值也不可變,因此只需要進(jìn)行一次計(jì)算。StringPool的需要如果一個(gè)String對(duì)象已經(jīng)被創(chuàng)建過(guò)了,那么就會(huì)從StringPool中取得引用。只有String是不可變的,才可能使用StringPool。安全性String經(jīng)常作為參數(shù),String不可變性可以保證參數(shù)不可變。例如在作為網(wǎng)絡(luò)連接參數(shù)的情況下如果String是可變的,那么在網(wǎng)絡(luò)連接過(guò)程中,String被改變,改變String對(duì)象的那一方以為現(xiàn)在連接的是其它主機(jī),而實(shí)際情況卻不一定是。線程安全String不可變性天生具備線程安全,可以在多個(gè)線程中安全地使用。Hashcode與equal區(qū)別,什么時(shí)候需要用到hashcode?講講里面的原理。如何解決Hash沖突?Hashcode與equal區(qū)別equals()比較兩個(gè)對(duì)象的地址值是否相等;hashCode()得到的是對(duì)象的存儲(chǔ)位置,可能不同對(duì)象會(huì)得到相同值有兩個(gè)對(duì)象,若equals()相等,則hashcode()一定相等;hashcode()不等,則equals()一定不相等;hashcode()相等,equals()可能相等、可能不等使用equals()比較兩個(gè)對(duì)象是否相等效率較低,最快辦法是先用hashCode()比較,如果hashCode()不相等,則這兩個(gè)對(duì)象肯定不相等;如果hashCode()相等,此時(shí)再用equal()比較,如果equal()也相等,則這兩個(gè)對(duì)象的確相等。什么時(shí)候需要用到hashcode同樣用于鑒定2個(gè)對(duì)象是否相等的,java集合中有l(wèi)ist和set兩類,其中set不允許元素重復(fù)實(shí)現(xiàn),那個(gè)這個(gè)不允許重復(fù)實(shí)現(xiàn)的方法,如果用equal去比較的話,如果存在1000個(gè)元素,你new一個(gè)新的元素出來(lái),需要去調(diào)用1000次equal去逐個(gè)和他們比較是否是同一個(gè)對(duì)象,這樣會(huì)大大降低效率。hashcode實(shí)際上是返回對(duì)象的存儲(chǔ)地址,如果這個(gè)位置上沒(méi)有元素,就把元素直接存儲(chǔ)在上面,如果這個(gè)位置上已經(jīng)存在元素,這個(gè)時(shí)候才去調(diào)用equal方法與新元素進(jìn)行比較,相同的話就不存了,散列到其他地址上技術(shù)博客大總結(jié)如何解決Hash沖突開(kāi)放定址法:常見(jiàn)的線性探測(cè)方式,在沖突發(fā)生時(shí),順序查看表中下一單元,直到找出一個(gè)空單元或查遍全表鏈地址法:將有沖突數(shù)組位置生出鏈表建立公共溢出區(qū):將哈希表分為基本表和溢出表兩部分,和基本表發(fā)生沖突的元素一律填入溢出表再哈希法:構(gòu)造多個(gè)不同的哈希函數(shù),有沖突使用下一個(gè)哈希函數(shù)計(jì)算hash值訪問(wèn)修飾符public,private,protected,以及不寫(xiě)(默認(rèn))時(shí)的區(qū)別?類的成員不寫(xiě)訪問(wèn)修飾時(shí)默認(rèn)為default。默認(rèn)對(duì)于同一個(gè)包中的其他類相當(dāng)于公開(kāi)(public),對(duì)于不是同一個(gè)包中的其他類相當(dāng)于私有(private)。受保護(hù)(protected)對(duì)子類相當(dāng)于公開(kāi),對(duì)不是同一包中的沒(méi)有父子關(guān)系的類相當(dāng)于私有。區(qū)別如下:作用域當(dāng)前類同包子類其他public√√√√protected√√√×default√√××private√×××靜態(tài)變量和實(shí)例變量的區(qū)別?成員變量與局部變量的區(qū)別有那些?靜態(tài)變量和實(shí)例變量的區(qū)別靜態(tài)變量是被static修飾符修飾的變量,也稱為類變量,它屬于類,不屬于類的任何一個(gè)對(duì)象,一個(gè)類不管創(chuàng)建多少個(gè)對(duì)象,靜態(tài)變量在內(nèi)存中有且僅有一個(gè)拷貝。靜態(tài)變量可以實(shí)現(xiàn)讓多個(gè)對(duì)象共享內(nèi)存。在Java開(kāi)發(fā)中,上下文類和工具類中通常會(huì)有大量的靜態(tài)成員。實(shí)例變量必須依存于某一實(shí)例,需要先創(chuàng)建對(duì)象然后通過(guò)對(duì)象才能訪問(wèn)到它成員變量與局部變量的區(qū)別1.從語(yǔ)法形式上,看成員變量是屬于類的,而局部變量是在方法中定義的變量或是方法的參數(shù);成員變量可以被public,private,static等修飾符所修飾,而局部變量不能被訪問(wèn)控制修飾符及static所修飾;但是,成員變量和局部變量都能被final所修飾;2.從變量在內(nèi)存中的存儲(chǔ)方式來(lái)看,成員變量是對(duì)象的一部分,而對(duì)象存在于堆內(nèi)存,局部變量存在于棧內(nèi)存3.從變量在內(nèi)存中的生存時(shí)間上看,成員變量是對(duì)象的一部分,它隨著對(duì)象的創(chuàng)建而存在,而局部變量隨著方法的調(diào)用而自動(dòng)消失。4.成員變量如果沒(méi)有被賦初值,則會(huì)自動(dòng)以類型的默認(rèn)值而賦值(一種情況例外被final修飾但沒(méi)有被static修飾的成員變量必須顯示地賦值);而局部變量則不會(huì)自動(dòng)賦值。如何實(shí)現(xiàn)對(duì)象克隆?深克隆,淺克隆分別說(shuō)的是什么意思?有兩種方式:1.實(shí)現(xiàn)Cloneable接口并重寫(xiě)Object類中的clone()方法;2.實(shí)現(xiàn)Serializable接口,通過(guò)對(duì)象的序列化和反序列化實(shí)現(xiàn)克隆,可以實(shí)現(xiàn)真正的深度克隆,代碼如下。注意問(wèn)題:基于序列化和反序列化實(shí)現(xiàn)的克隆不僅僅是深度克隆,更重要的是通過(guò)泛型限定,可以檢查出要克隆的對(duì)象是否支持序列化,這項(xiàng)檢查是編譯器完成的,不是在運(yùn)行時(shí)拋出異常,這種是方案明顯優(yōu)于使用Object類的clone方法克隆對(duì)象。代碼如下所示publicclassMyUtil{privateMyUtil(){

thrownewAssertionError();

}

publicstatic<T>Tclone(Tobj)throwsException{

ByteArrayOutputStreambout=newByteArrayOutputStream();

ObjectOutputStreamoos=newObjectOutputStream(bout);

oos.writeObject(obj);

ByteArrayInputStreambin=newByteArrayInputStream(bout.toByteArray());

ObjectInputStreamois=newObjectInputStream(bin);

return(T)ois.readObject();

//說(shuō)明:調(diào)用ByteArrayInputStream或ByteArrayOutputStream對(duì)象的close方法沒(méi)有任何意義

//這兩個(gè)基于內(nèi)存的流只要垃圾回收器清理對(duì)象就能夠釋放資源

}}classCloneTest{publicstaticvoidmain(String[]args){try{Personp1=newPerson("HaoLUO",33,newCar("Benz",300));Personp2=MyUtil.clone(p1);//深度克隆p2.getCar().setBrand("BYD");//修改克隆的Person對(duì)象p2關(guān)聯(lián)的汽車對(duì)象的品牌屬性//原來(lái)的Person對(duì)象p1關(guān)聯(lián)的汽車不會(huì)受到任何影響//因?yàn)樵诳寺erson對(duì)象時(shí)其關(guān)聯(lián)的汽車對(duì)象也被克隆了System.out.println(p1);}catch(Exceptione){e.printStackTrace();}}}通過(guò)反射獲得泛型的實(shí)際類型參數(shù)把泛型變量當(dāng)成方法的參數(shù),利用Method類的getGenericParameterTypes方法來(lái)獲取泛型的實(shí)際類型參數(shù)例子:publicclassGenericTest{publicstaticvoidmain(String[]args)throwsException{

getParamType();

}

/*利用反射獲取方法參數(shù)的實(shí)際參數(shù)類型*/

publicstaticvoidgetParamType()throwsNoSuchMethodException{

Methodmethod=GenericTest.class.getMethod("applyMap",Map.class);

//獲取方法的泛型參數(shù)的類型

Type[]types=method.getGenericParameterTypes();

System.out.println(types[0]);

//參數(shù)化的類型

ParameterizedTypepType=(ParameterizedType)types[0];

//原始類型

System.out.println(pType.getRawType());

//實(shí)際類型參數(shù)

System.out.println(pType.getActualTypeArguments()[0]);

System.out.println(pType.getActualTypeArguments()[1]);

}

/*供測(cè)試參數(shù)類型的方法*/

publicstaticvoidapplyMap(Map<Integer,String>map){

}}輸出結(jié)果:java.util.Map<java.lang.Integer,java.lang.String>interfacejava.util.Mapclassjava.lang.Integerclassjava.lang.Stringint和Integer的區(qū)別?裝箱、拆箱什么含義?什么時(shí)候裝箱/拆箱?裝箱和拆箱是如何實(shí)現(xiàn)的?int和Integer的區(qū)別:基本數(shù)據(jù)類型、引用類型Integer是int的包裝類,int則是java的一種基本數(shù)據(jù)類型Integer變量必須實(shí)例化后才能使用,而int變量不需要Integer實(shí)際是對(duì)象的引用,當(dāng)new一個(gè)Integer時(shí),實(shí)際上是生成一個(gè)指針指向此對(duì)象;而int則是直接存儲(chǔ)數(shù)據(jù)值Integer的默認(rèn)值是null,int的默認(rèn)值是0裝箱、拆箱裝箱就是自動(dòng)將基本數(shù)據(jù)類型轉(zhuǎn)換為包裝器類型拆箱就是自動(dòng)將包裝器類型轉(zhuǎn)換為基本數(shù)據(jù)類型//拆箱intyc=5;//裝箱Integeryc=5;jdk中如何操作裝箱、拆箱在JDK中,裝箱過(guò)程是通過(guò)調(diào)用包裝器的valueOf方法實(shí)現(xiàn)的,而拆箱過(guò)程是通過(guò)調(diào)用包裝器的xxxValue方法實(shí)現(xiàn)的(xxx代表對(duì)應(yīng)的基本數(shù)據(jù)類型)。Integer、Short、Byte、Character、Long這幾個(gè)類的valueOf方法的實(shí)現(xiàn)是類似的,有限可列舉,共享[-128,127];Double、Float的valueOf方法的實(shí)現(xiàn)是類似的,無(wú)限不可列舉,不共享;Boolean的valueOf方法的實(shí)現(xiàn)不同于以上的整型和浮點(diǎn)型,只有兩個(gè)值,有限可列舉,共享;什么時(shí)候裝箱/拆箱?什么時(shí)候拆箱主要取決于:在當(dāng)前場(chǎng)景下,你需要的是引用類型還是原生類型。若需要引用類型,但傳進(jìn)來(lái)的值是原生類型,則自動(dòng)裝箱(例如,使用equals方法時(shí)傳進(jìn)來(lái)原生類型的值);若需要的是原生類型,但傳進(jìn)來(lái)的值是引用類型,則自動(dòng)拆箱(例如,使用運(yùn)算符進(jìn)行運(yùn)算時(shí),操作數(shù)是包裝類型)。裝箱和拆箱是如何實(shí)現(xiàn)的以Interger類為例,下面看一段代碼來(lái)了解裝箱和拆箱的實(shí)現(xiàn)publicclassMain{publicstaticvoidmain(String[]args){Integery=10;intc=i;}}然后來(lái)編譯一下:從反編譯得到的字節(jié)碼內(nèi)容可以看出,在裝箱的時(shí)候自動(dòng)調(diào)用的是Integer的valueOf(int)方法。而在拆箱的時(shí)候自動(dòng)調(diào)用的是Integer的intValue方法。因此可以用一句話總結(jié)裝箱和拆箱的實(shí)現(xiàn)過(guò)程:裝箱過(guò)程是通過(guò)調(diào)用包裝器的valueOf方法實(shí)現(xiàn)的,而拆箱過(guò)程是通過(guò)調(diào)用包裝器的xxxValue方法實(shí)現(xiàn)的。(xxx代表對(duì)應(yīng)的基本數(shù)據(jù)類型)。Object有哪些公有方法?常用方法equals():和==作用相似hashCode():用于哈希查找,重寫(xiě)了equals()一般都要重寫(xiě)該方法getClass():獲取Class對(duì)象wait():讓當(dāng)前線程進(jìn)入等待狀態(tài),并釋放它所持有的鎖notify()¬ifyAll():?jiǎn)拘岩粋€(gè)(所有)正處于等待狀態(tài)的線程toString():轉(zhuǎn)換成字符串final,finally,finalize有什么不同?finally什么情況下不會(huì)被執(zhí)行?final可以修飾類,方法,變量final修飾類代表類不可以繼承拓展final修飾變量表示變量不可以修改final修飾方法表示方法不可以被重寫(xiě)finally則是Java保證重點(diǎn)代碼一定要被執(zhí)行的一種機(jī)制可以使用try-finally或者try-catch-finally來(lái)進(jìn)行類似關(guān)閉JDBC連接、保證unlock鎖等動(dòng)作。finalize是基礎(chǔ)類java.lang.Object的一個(gè)方法它的設(shè)計(jì)目的是保證對(duì)象在被垃圾收集前完成特定資源的回收。finalize機(jī)制現(xiàn)在已經(jīng)不推薦使用,并且在JDK9開(kāi)始被標(biāo)記為deprecated。final關(guān)鍵字深入理解可以將方法或者類聲明為final,這樣就可以明確告知?jiǎng)e人,這些行為是不許修改的。如果你關(guān)注過(guò)Java核心類庫(kù)的定義或源碼,有沒(méi)有發(fā)現(xiàn)java.lang包下面的很多類,相當(dāng)一部分都被聲明成為finalclass?在第三方類庫(kù)的一些基礎(chǔ)類中同樣如此,這可以有效避免API使用者更改基礎(chǔ)功能,某種程度上,這是保證平臺(tái)安全的必要手段。使用final修飾參數(shù)或者變量,也可以清楚地避免意外賦值導(dǎo)致的編程錯(cuò)誤,甚至,有人明確推薦將所有方法參數(shù)、本地變量、成員變量聲明成final。final變量產(chǎn)生了某種程度的不可變(immutable)的效果,所以,可以用于保護(hù)只讀數(shù)據(jù),尤其是在并發(fā)編程中,因?yàn)槊鞔_地不能再賦值final變量,有利于減少額外的同步開(kāi)銷,也可以省去一些防御性拷貝的必要。在以下4種特殊情況下,finally塊不會(huì)被執(zhí)行:1.在finally語(yǔ)句塊中發(fā)生了異常。2.在前面的代碼中用了System.exit()退出程序。3.程序所在的線程死亡。4.關(guān)閉CPU。為什么要使用通配符?上界通配符和下界通配符如何理解和注意要點(diǎn)?什么是×××通配符?為什么要使用通配符通配符的設(shè)計(jì)存在一定的場(chǎng)景,例如在使用泛型后,首先聲明了一個(gè)Animal的類,而后聲明了一個(gè)繼承Animal類的Cat類,顯然Cat類是Animal類的子類,但是List<Cat>卻不是List<Animal>的子類型,而在程序中往往需要表達(dá)這樣的邏輯關(guān)系。為了解決這種類似的場(chǎng)景,在泛型的參數(shù)類型的基礎(chǔ)上新增了通配符的用法。<?extendsT>上界通配符-上界通配符顧名思義,<?extendsT>表示的是類型的上界【包含自身】,因此通配的參數(shù)化類型可能是T或T的子類。正因?yàn)闊o(wú)法確定具體的類型是什么,add方法受限(可以添加null,因?yàn)閚ull表示任何類型),但可以從列表中獲取元素后賦值給父類型。如上圖中的第一個(gè)例子,第三個(gè)add()操作會(huì)受限,原因在于List<Animal>和List<Cat>是List<?extendsAnimal>的子類型。<?superT>下界通配符-下界通配符<?superT>表示的是參數(shù)化類型是T的超類型(包含自身),層層至上,直至Object,編譯器無(wú)從判斷get()返回的對(duì)象的類型是什么,因此get()方法受限。但是可以進(jìn)行add()方法,add()方法可以添加T類型和T類型的子類型,如第二個(gè)例子中首先添加了一個(gè)Cat類型對(duì)象,然后添加了兩個(gè)Cat子類類型的對(duì)象,這種方法是可行的,但是如果添加一個(gè)Animal類型的對(duì)象,顯然將繼承的關(guān)系弄反了,是不可行的。<?>×××通配符任意類型,如果沒(méi)有明確,那么就是Object以及任意的Java類了×××通配符用<?>表示,?代表了任何的一種類型,能代表任何一種類型的只有null(Object本身也算是一種類型,但卻不能代表任何一種類型,所以List<Object>和List<null>的含義是不同的,前者類型是Object,也就是繼承樹(shù)的最上層,而后者的類型完全是未知的)。技術(shù)博客大總結(jié)什么是泛型擦除,能否通過(guò)開(kāi)發(fā)中實(shí)際案例說(shuō)下?如何獲取泛型的具體的類型【反射】?開(kāi)發(fā)中的泛型擦除案例泛型是提供給javac編譯器使用的,限定集合的輸入類型,編譯器編譯帶類型說(shuō)明的集合時(shí)會(huì)去掉“類型”信息。publicclassGenericTest{publicstaticvoidmain(String[]args){newGenericTest().testType();}publicvoidtestType(){ArrayList<Integer>collection1=newArrayList<Integer>();ArrayList<String>collection2=newArrayList<String>();System.out.println(collection1.getClass()==collection2.getClass());//兩者class類型一樣,即字節(jié)碼一致System.out.println(collection2.getClass().getName());//class均為java.util.ArrayList,并無(wú)實(shí)際類型參數(shù)信息}//輸出結(jié)果

//true

//java.util.ArrayList}如何獲取泛型的具體的類型?使用反射可跳過(guò)編譯器,往某個(gè)泛型集合加入其它類型數(shù)據(jù)。只有引用類型才能作為泛型方法的實(shí)際參數(shù),具體案例如下所示publicclassGenericTest{publicstaticvoidmain(String[]args){swap(newString[]{"111","222"},0,1);//編譯通過(guò)//swap(newint[]{1,2},0,1);

//編譯不通過(guò),因?yàn)閕nt不是引用類型

swap(newInteger[]{1,2},0,1);//編譯通過(guò)

}

/*交換數(shù)組a的第i個(gè)和第j個(gè)元素*/

publicstatic<T>voidswap(T[]a,inti,intj){

Ttemp=a[i];

a[i]=a[j];

a[j]=temp;

}}但注意基本類型有時(shí)可以作為實(shí)參,因?yàn)橛凶詣?dòng)裝箱和拆箱。下面例子(編譯通過(guò)了):publicclassGenericTest{publicstaticvoidmain(String[]args){newGenericTest().testType();inta=biggerOne(3,5);//int和double,取交為NumberNumberb=biggerOne(3,5.5);//String和int取交為ObjectObjectc=biggerOne("1",2);}//從x,y中返回ypublicstatic<T>TbiggerOne(Tx,Ty){returny;}}同時(shí),該例還表明,當(dāng)實(shí)參不一致時(shí),T取交集,即第一個(gè)共同的父類。另外,如果用Numberb=biggerOne(3,5.5);改為Stringc=biggerOne(3,5.5);則編譯報(bào)錯(cuò):Error:(17,29)java:不兼容的類型:推斷類型不符合上限推斷:java.lang.Number&java.lang.Comparable<?extendsjava.lang.Number&java.lang.Comparable<?>>上限:java.lang.String,java.lang.Object如何驗(yàn)證int類型是否線程安全?那些類型是線程安全的?舉一個(gè)線程安全的例子【AtomicInteger】?如何驗(yàn)證int類型是否線程安全200個(gè)線程,每個(gè)線程對(duì)共享變量count進(jìn)行50次++操作int作為基本類型,直接存儲(chǔ)在內(nèi)存棧,且對(duì)其進(jìn)行+,-操作以及++,–操作都不是原子操作,都有可能被其他線程搶斷,所以不是線程安全。int用于單線程變量存取,開(kāi)銷小,速度快技術(shù)博客大總結(jié)intcount=0;privatevoidstartThread(){for(inti=0;i<200;i++){newThread(newRunnable(){@Overridebr/>@Overridefor(intk=0;k<50;k++){count++;}}}).start();}//休眠10秒,以確保線程都已啟動(dòng)try{Thread.sleep(1000*10);}catch(InterruptedExceptione){e.printStackTrace();}finally{Log.e("打印日志",count+"");}}//期望輸出10000,最后輸出的是9818//注意:打印日志:9818那些類型是線程安全的Java自帶的線程安全的基本類型包括:AtomicInteger,AtomicLong,AtomicBoolean,AtomicIntegerArray,AtomicLongArray等AtomicInteger線程安全版AtomicInteger類中有有一個(gè)變量valueOffset,用來(lái)描述AtomicInteger類中value的內(nèi)存位置。當(dāng)需要變量的值改變的時(shí)候,先通過(guò)get()得到valueOffset位置的值,也即當(dāng)前value的值.給該值進(jìn)行增加,并賦給nextcompareAndSet()比較之前取到的value的值當(dāng)前有沒(méi)有改變,若沒(méi)有改變的話,就將next的值賦給value,倘若和之前的值相比的話發(fā)生變化的話,則重新一次循環(huán),直到存取成功,通過(guò)這樣的方式能夠保證該變量是線程安全的value使用了volatile關(guān)鍵字,使得多個(gè)線程可以共享變量,使用volatile將使得VM優(yōu)化失去作用,在線程數(shù)特別大時(shí),效率會(huì)較低。privatestaticAtomicIntegeratomicInteger=newAtomicInteger(1);staticIntegercount1=Integer.valueOf(0);privatevoidstartThread1(){for(inti=0;i<200;i++){newThread(newRunnable(){@Overridebr/>@Overridefor(intk=0;k<50;k++){//getAndIncrement:先獲得值,再自增1,返回值為自增前的值count1=atomicInteger.getAndIncrement();}}}).start();}//休眠10秒,以確保線程都已啟動(dòng)try{Thread.sleep(1000*10);}catch(InterruptedExceptione){e.printStackTrace();}finally{Log.e("打印日志",count1+"");}}//期望輸出10000,最后輸出的是10000//注意:打印日志:10000//AtomicInteger使用了volatile關(guān)鍵字進(jìn)行修飾,使得該類可以滿足線程安全。privatevolatileintvalue;publicAtomicInteger(intinitialValue){value=initialValue;}Java序列話中如果有些字段不想進(jìn)行序列化怎么辦?對(duì)于不想進(jìn)行序列化的變量,使用transient關(guān)鍵字修飾。transient關(guān)鍵字的作用是:阻止實(shí)例中那些用此關(guān)鍵字修飾的的變量序列化;當(dāng)對(duì)象被反序列化時(shí),被transient修飾的變量值不會(huì)被持久化和恢復(fù)。transient只能修飾變量,不能修飾類和方法。原始數(shù)據(jù)類型和引用類型局限性?為何要引用基本數(shù)據(jù)包裝類?原始數(shù)據(jù)類型和引用類型局限性原始數(shù)據(jù)類型和Java泛型并不能配合使用Java的泛型某種程度上可以算作偽泛型,它完全是一種編譯期的技巧,Java編譯期會(huì)自動(dòng)將類型轉(zhuǎn)換為對(duì)應(yīng)的特定類型,這就決定了使用泛型,必須保證相應(yīng)類型可以轉(zhuǎn)換為Object。為何要引用基本數(shù)據(jù)包裝類就比如,我們使用泛型,需要用到基本數(shù)據(jù)類型的包裝類。Java的對(duì)象都是引用類型,如果是一個(gè)原始數(shù)據(jù)類型數(shù)組,它在內(nèi)存里是一段連續(xù)的內(nèi)存,而對(duì)象數(shù)組則不然,數(shù)據(jù)存儲(chǔ)的是引用,對(duì)象往往是分散地存儲(chǔ)在堆的不同位置。這種設(shè)計(jì)雖然帶來(lái)了極大靈活性,但是也導(dǎo)致了數(shù)據(jù)操作的低效,尤其是無(wú)法充分利用現(xiàn)代CPU緩存機(jī)制。Java為對(duì)象內(nèi)建了各種多態(tài)、線程安全等方面的支持,但這不是所有場(chǎng)合的需求,尤其是數(shù)據(jù)處理重要性日益提高,更加高密度的值類型是非?,F(xiàn)實(shí)的需求。newInteger(123)與Integer.valueOf(123)有何區(qū)別,請(qǐng)從底層實(shí)現(xiàn)分析兩者區(qū)別?newInteger(123)與Integer.valueOf(123)的區(qū)別在于:newInteger(123)每次都會(huì)新建一個(gè)對(duì)象;Integer.valueOf(123)會(huì)使用緩存池中的對(duì)象,多次調(diào)用會(huì)取得同一個(gè)對(duì)象的引用。Integerx=newInteger(123);Integery=newInteger(123);System.out.println(x==y);//falseIntegerz=Integer.valueOf(123);Integerk=Integer.valueOf(123);System.out.println(z==k);//truevalueOf()方法的實(shí)現(xiàn)比較簡(jiǎn)單,就是先判斷值是否在緩存池中,如果在的話就直接返回緩存池的內(nèi)容。publicstaticIntegervalueOf(inti){if(i>=IntegerCache.low&&i<=IntegerCache.high)returnIntegerCache.cache[i+(-IntegerCache.low)];returnnew

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論