一. 類的加載過(guò)程
1).因?yàn)閚ew用到了Person.class,所以會(huì)先找到Person.class文件姻报,并加載到內(nèi)存中;
2).執(zhí)行該類中的static代碼塊瞒滴,如果有的話鹤耍,給Person.class類進(jìn)行初始化;
3).在堆內(nèi)存中開辟空間分配內(nèi)存地址;
4).在堆內(nèi)存中建立對(duì)象的特有屬性城豁,并進(jìn)行默認(rèn)初始化;
5).對(duì)屬性進(jìn)行顯示初始化;
6).對(duì)對(duì)象進(jìn)行構(gòu)造代碼塊初始化;
7).對(duì)對(duì)象進(jìn)行與之對(duì)應(yīng)的構(gòu)造函數(shù)進(jìn)行初始化;
8).將內(nèi)存地址付給棧內(nèi)存中的p變量
二. JVM相關(guān)知識(shí)苟穆,GC機(jī)制。
1.類加載器(ClassLoader):在JVM啟動(dòng)時(shí)或者在類運(yùn)行時(shí)將需要的class加載到JVM中唱星。(下圖表示了從java源文件到JVM的整個(gè)過(guò)程雳旅,可配合理解
2.執(zhí)行引擎:負(fù)責(zé)執(zhí)行class文件中包含的字節(jié)碼指令;
3.內(nèi)存區(qū)(也叫運(yùn)行時(shí)數(shù)據(jù)區(qū)):是在JVM運(yùn)行的時(shí)候操作所分配的內(nèi)存區(qū)魏颓。運(yùn)行時(shí)內(nèi)存區(qū)主要可以劃分為5個(gè)區(qū)域岭辣,如圖:
方法區(qū)(Method Area):用于存儲(chǔ)類結(jié)構(gòu)信息的地方,包括常量池甸饱、靜態(tài)變量、構(gòu)造函數(shù)等仑濒。雖然JVM規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分叹话, 但它卻有個(gè)別名non-heap(非堆),所以大家不要搞混淆了墩瞳。方法區(qū)還包含一個(gè)運(yùn)行時(shí)常量池驼壶。
java堆(Heap):存儲(chǔ)java實(shí)例或者對(duì)象的地方。這塊是GC的主要區(qū)域喉酌。從存儲(chǔ)的內(nèi)容我們可以很容易知道热凹,方法區(qū)和堆是被所有java線程共享的泵喘。
java棧(Stack):java棧總是和線程關(guān)聯(lián)在一起般妙,每當(dāng)創(chuàng)建一個(gè)線程時(shí)纪铺,JVM就會(huì)為這個(gè)線程創(chuàng)建一個(gè)對(duì)應(yīng)的java棧。在這個(gè)java棧中又會(huì)包含多個(gè)棧幀碟渺,每運(yùn)行一個(gè)方法就創(chuàng)建一個(gè)棧幀鲜锚,用于存儲(chǔ)局部變量表、操作棧苫拍、方法返回值等芜繁。每一個(gè)方法從調(diào)用直至執(zhí)行完成的過(guò)程,就對(duì)應(yīng)一個(gè)棧幀在java棧中入棧到出棧的過(guò)程绒极。所以java棧是現(xiàn)成私有的骏令。
程序計(jì)數(shù)器(PC Register):用于保存當(dāng)前線程執(zhí)行的內(nèi)存地址。由于JVM程序是多線程執(zhí)行的(線程輪流切換)垄提,所以為了保證線程切換回來(lái)后伏社,還能恢復(fù)到原先狀態(tài),就需要一個(gè)獨(dú)立的計(jì)數(shù)器塔淤,記錄之前中斷的地方摘昌,可見程序計(jì)數(shù)器也是線程私有的。
本地方法棧(Native Method Stack):和java棧的作用差不多高蜂,只不過(guò)是為JVM使用到的native方法服務(wù)的聪黎。
4.本地方法接口:主要是調(diào)用C或C++實(shí)現(xiàn)的本地方法及返回結(jié)果。
GC機(jī)制
垃圾收集器一般必須完成兩件事:檢測(cè)出垃圾备恤;回收垃圾稿饰。怎么檢測(cè)出垃圾?一般有以下幾種方法:
引用計(jì)數(shù)法:
給一個(gè)對(duì)象添加引用計(jì)數(shù)器露泊,每當(dāng)有個(gè)地方引用它喉镰,計(jì)數(shù)器就加1;引用失效就減1惭笑。好了侣姆,問(wèn)題來(lái)了,如果我有兩個(gè)對(duì)象A和B沉噩,互相引用捺宗,除此之外,沒(méi)有其他任何對(duì)象引用它們川蒙,實(shí)際上這兩個(gè)對(duì)象已經(jīng)無(wú)法訪問(wèn)蚜厉,即是我們說(shuō)的垃圾對(duì)象。但是互相引用畜眨,計(jì)數(shù)不為0昼牛,導(dǎo)致無(wú)法回收术瓮,所以還有另一種方法:
可達(dá)性分析算法:
以根集對(duì)象為起始點(diǎn)進(jìn)行搜索,如果有對(duì)象不可達(dá)的話贰健,即是垃圾對(duì)象胞四。這里的根集一般包括java棧中引用的對(duì)象、方法區(qū)常良池中引用的對(duì)象霎烙、本地方法中引用的對(duì)象等撬讽。
總之,JVM在做垃圾回收的時(shí)候悬垃,會(huì)檢查堆中的所有對(duì)象是否會(huì)被這些根集對(duì)象引用游昼,不能夠被引用的對(duì)象就會(huì)被垃圾收集器回收。一般回收算法也有如下幾種:
1).標(biāo)記-清除(Mark-sweep)
2).復(fù)制(Copying
3).標(biāo)記-整理(Mark-Compact)
4).分代收集算法
三. 類的加載器尝蠕,雙親機(jī)制烘豌,Android的類加載器。
類的加載器
大家都知道看彼,當(dāng)我們寫好一個(gè)Java程序之后廊佩,不是管是CS還是BS應(yīng)用,都是由若干個(gè).class文件組織而成的一個(gè)完整的Java應(yīng)用程序靖榕,當(dāng)程序在運(yùn)行時(shí)标锄,即會(huì)調(diào)用該程序的一個(gè)入口函數(shù)來(lái)調(diào)用系統(tǒng)的相關(guān)功能,而這些功能都被封裝在不同的class文件當(dāng)中茁计,所以經(jīng)常要從這個(gè)class文件中要調(diào)用另外一個(gè)class文件中的方法料皇,如果另外一個(gè)文件不存在的,則會(huì)引發(fā)系統(tǒng)異常星压。
而程序在啟動(dòng)的時(shí)候践剂,并不會(huì)一次性加載程序所要用的所有class文件,而是根據(jù)程序的需要娜膘,通過(guò)Java的類加載機(jī)制(ClassLoader)來(lái)動(dòng)態(tài)加載某個(gè)class文件到內(nèi)存當(dāng)中的逊脯,從而只有class文件被載入到了內(nèi)存之后,才能被其它c(diǎn)lass所引用竣贪。所以ClassLoader就是用來(lái)動(dòng)態(tài)加載class文件到內(nèi)存當(dāng)中用的军洼。
雙親機(jī)制
1、原理介紹
ClassLoader使用的是雙親委托模型來(lái)搜索類的贾富,每個(gè)ClassLoader實(shí)例都有一個(gè)父類加載器的引用(不是繼承的關(guān)系歉眷,是一個(gè)包含的關(guān)系),虛擬機(jī)內(nèi)置的類加載器(Bootstrap ClassLoader)本身沒(méi)有父類加載器颤枪,但可以用作其它ClassLoader實(shí)例的的父類加載器。
當(dāng)一個(gè)ClassLoader實(shí)例需要加載某個(gè)類時(shí)淑际,它會(huì)試圖親自搜索某個(gè)類之前畏纲,先把這個(gè)任務(wù)委托給它的父類加載器扇住,這個(gè)過(guò)程是由上至下依次檢查的,首先由最頂層的類加載器Bootstrap ClassLoader試圖加載盗胀,如果沒(méi)加載到艘蹋,則把任務(wù)轉(zhuǎn)交給Extension ClassLoader試圖加載,如果也沒(méi)加載到票灰,則轉(zhuǎn)交給App ClassLoader 進(jìn)行加載女阀,如果它也沒(méi)有加載得到的話,則返回給委托的發(fā)起者屑迂,由它到指定的文件系統(tǒng)或網(wǎng)絡(luò)等URL中加載該類浸策。
如果它們都沒(méi)有加載到這個(gè)類時(shí),則拋出ClassNotFoundException異常惹盼。否則將這個(gè)找到的類生成一個(gè)類的定義庸汗,并將它加載到內(nèi)存當(dāng)中,最后返回這個(gè)類在內(nèi)存中的Class實(shí)例對(duì)象手报。
2蚯舱、為什么要使用雙親委托這種模型呢?
因?yàn)檫@樣可以避免重復(fù)加載掩蛤,當(dāng)父親已經(jīng)加載了該類的時(shí)候枉昏,就沒(méi)有必要子ClassLoader再加載一次。
考慮到安全因素揍鸟,我們?cè)囅胍幌滦至眩绻皇褂眠@種委托模式,那我們就可以隨時(shí)使用自定義的String來(lái)動(dòng)態(tài)替代java核心api中定義的類型蜈亩,這樣會(huì)存在非常大的安全隱患懦窘,而雙親委托的方式,就可以避免這種情況稚配,因?yàn)镾tring已經(jīng)在啟動(dòng)時(shí)就被引導(dǎo)類加載器(Bootstrcp ClassLoader)加載畅涂,所以用戶自定義的ClassLoader永遠(yuǎn)也無(wú)法加載一個(gè)自己寫的String,除非你改變JDK中ClassLoader搜索類的默認(rèn)算法道川。
3午衰、但是JVM在搜索類的時(shí)候,又是如何判定兩個(gè)class是相同的呢冒萄?
JVM在判定兩個(gè)class是否相同時(shí)臊岸,不僅要判斷兩個(gè)類名是否相同,而且要判斷是否由同一個(gè)類加載器實(shí)例加載的尊流。
只有兩者同時(shí)滿足的情況下帅戒,JVM才認(rèn)為這兩個(gè)class是相同的。就算兩個(gè)class是同一份class字節(jié)碼崖技,如果被兩個(gè)不同的ClassLoader實(shí)例所加載逻住,JVM也會(huì)認(rèn)為它們是兩個(gè)不同class钟哥。
比如網(wǎng)絡(luò)上的一個(gè)Java類org.classloader.simple.NetClassLoaderSimple,javac編譯之后生成字節(jié)碼文件NetClassLoaderSimple.class瞎访,ClassLoaderA和ClassLoaderB這兩個(gè)類加載器并讀取了NetClassLoaderSimple.class文件腻贰,并分別定義出了java.lang.Class實(shí)例來(lái)表示這個(gè)類,對(duì)于JVM來(lái)說(shuō)扒秸,它們是兩個(gè)不同的實(shí)例對(duì)象播演,但它們確實(shí)是同一份字節(jié)碼文件,如果試圖將這個(gè)Class實(shí)例生成具體的對(duì)象進(jìn)行轉(zhuǎn)換時(shí)伴奥,就會(huì)拋運(yùn)行時(shí)異常java.lang.ClassCaseException写烤,提示這是兩個(gè)不同的類型。
Android類加載器
對(duì)于Android而言渔伯,最終的apk文件包含的是dex類型的文件顶霞,dex文件是將class文件重新打包,打包的規(guī)則又不是簡(jiǎn)單地壓縮锣吼,而是完全對(duì)class文件內(nèi)部的各種函數(shù)表选浑,變量表進(jìn)行優(yōu)化,產(chǎn)生一個(gè)新的文件玄叠,即dex文件古徒。因此加載這種特殊的Class文件就需要特殊的類加載器DexClassLoader。
四. 集合框架读恃,list隧膘,map,set都有哪些具體的實(shí)現(xiàn)類寺惫,區(qū)別都是什么?
1.List,Set都是繼承自Collection接口疹吃,Map則不是;
2.List特點(diǎn):元素有放入順序,元素可重復(fù);
Set特點(diǎn):元素?zé)o放入順序西雀,元素不可重復(fù)萨驶,重復(fù)元素會(huì)覆蓋掉,(注意:元素雖然無(wú)放入順序艇肴,但是元素在set中的位置是有該元素的HashCode決定的腔呜,其位置其實(shí)是固定的,加入Set 的Object必須定義equals()方法;
另外list支持for循環(huán)再悼,也就是通過(guò)下標(biāo)來(lái)遍歷核畴,也可以用迭代器,但是set只能用迭代冲九,因?yàn)樗麩o(wú)序谤草,無(wú)法用下標(biāo)來(lái)取得想要的值)。
3.Set和List對(duì)比:
Set:檢索元素效率低下,刪除和插入效率高咖刃,插入和刪除不會(huì)引起元素位置改變泳炉。
List:和數(shù)組類似憾筏,List可以動(dòng)態(tài)增長(zhǎng)嚎杨,查找元素效率高,插入刪除元素效率低氧腰,因?yàn)闀?huì)引起其他元素位置改變枫浙。
4.Map適合儲(chǔ)存鍵值對(duì)的數(shù)據(jù)。
5.線程安全集合類與非線程安全集合類
LinkedList古拴、ArrayList箩帚、HashSet是非線程安全的,Vector是線程安全的;
HashMap是非線程安全的黄痪,HashTable是線程安全的;
StringBuilder是非線程安全的紧帕,StringBuffer是線程安全的。
下面是這些類具體的使用介紹:
ArrayList與LinkedList的區(qū)別和適用場(chǎng)景
Arraylist:
優(yōu)點(diǎn):ArrayList是實(shí)現(xiàn)了基于動(dòng)態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),因?yàn)榈刂愤B續(xù)桅打,一旦數(shù)據(jù)存儲(chǔ)好了是嗜,查詢操作效率會(huì)比較高(在內(nèi)存里是連著放的)。
缺點(diǎn):因?yàn)榈刂愤B續(xù)挺尾, ArrayList要移動(dòng)數(shù)據(jù),所以插入和刪除操作效率比較低鹅搪。
LinkedList:
優(yōu)點(diǎn):LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu),地址是任意的,所以在開辟內(nèi)存空間的時(shí)候不需要等一個(gè)連續(xù)的地址遭铺,對(duì)于新增和刪除操作add和remove丽柿,LinedList比較占優(yōu)勢(shì)。LinkedList 適用于要頭尾操作或插入指定位置的場(chǎng)景魂挂。
缺點(diǎn):因?yàn)長(zhǎng)inkedList要移動(dòng)指針,所以查詢操作性能比較低甫题。
適用場(chǎng)景分析:
當(dāng)需要對(duì)數(shù)據(jù)進(jìn)行對(duì)此訪問(wèn)的情況下選用ArrayList,當(dāng)需要對(duì)數(shù)據(jù)進(jìn)行多次增加刪除修改時(shí)采用LinkedList涂召。
ArrayList與Vector的區(qū)別和適用場(chǎng)景
ArrayList有三個(gè)構(gòu)造方法:
public ArrayList(int initialCapacity)//構(gòu)造一個(gè)具有指定初始容量的空列表坠非。
public ArrayList()//構(gòu)造一個(gè)初始容量為10的空列表。
public ArrayList(Collection<? extends E> c)//構(gòu)造一個(gè)包含指定 collection 的元素的列表
Vector有四個(gè)構(gòu)造方法:
public Vector() // 使用指定的初始容量和等于零的容量增量構(gòu)造一個(gè)空向量芹扭。
public Vector(int initialCapacity) // 構(gòu)造一個(gè)空向量麻顶,使其內(nèi)部數(shù)據(jù)數(shù)組的大小,其標(biāo)準(zhǔn)容量增量為零舱卡。
public Vector(Collection<? extends E> c)// 構(gòu)造一個(gè)包含指定 collection 中的元素的向量
public Vector(int initialCapacity,int capacityIncrement)//使用指定的初始容量和容量增量構(gòu)造一個(gè)空的向量
ArrayList和Vector都是用數(shù)組實(shí)現(xiàn)的辅肾,主要有這么三個(gè)區(qū)別:
1).Vector是多線程安全的,線程安全就是說(shuō)多線程訪問(wèn)同一代碼轮锥,不會(huì)產(chǎn)生不確定的結(jié)果矫钓。而ArrayList不是,這個(gè)可以從源碼中看出,Vector類中的方法很多有synchronized進(jìn)行修飾新娜,這樣就導(dǎo)致了Vector在效率上無(wú)法與ArrayList相比赵辕;
2).兩個(gè)都是采用的線性連續(xù)空間存儲(chǔ)元素,但是當(dāng)空間不足的時(shí)候概龄,兩個(gè)類的增加方式是不同还惠。
3).Vector可以設(shè)置增長(zhǎng)因子,而ArrayList不可以私杜。
4).Vector是一種老的動(dòng)態(tài)數(shù)組蚕键,是線程同步的,效率很低衰粹,一般不贊成使用锣光。
適用場(chǎng)景:
1.Vector是線程同步的,所以它也是線程安全的铝耻,而ArrayList是線程異步的誊爹,是不安全的。如果不考慮到線程的安全因素瓢捉,一般用ArrayList效率比較高频丘。
2.如果集合中的元素的數(shù)目大于目前集合數(shù)組的長(zhǎng)度時(shí),在集合中使用數(shù)據(jù)量比較大的數(shù)據(jù)泊柬,用Vector有一定的優(yōu)勢(shì)椎镣。
HashSet與Treeset的適用場(chǎng)景
1.TreeSet 是二叉樹(紅黑樹的樹據(jù)結(jié)構(gòu))實(shí)現(xiàn)的,Treeset中的數(shù)據(jù)是自動(dòng)排好序的,不允許放入null值兽赁。
2.HashSet 是哈希表實(shí)現(xiàn)的,HashSet中的數(shù)據(jù)是無(wú)序的状答,可以放入null,但只能放入一個(gè)null刀崖,兩者中的值都不能重復(fù)惊科,就如數(shù)據(jù)庫(kù)中唯一約束。
3.HashSet要求放入的對(duì)象必須實(shí)現(xiàn)HashCode()方法亮钦,放入的對(duì)象馆截,是以hashcode碼作為標(biāo)識(shí)的,而具有相同內(nèi)容的String對(duì)象蜂莉,hashcode是一樣蜡娶,所以放入的內(nèi)容不能重復(fù)。但是同一個(gè)類的對(duì)象可以放入不同的實(shí)例映穗。
適用場(chǎng)景分析:
HashSet是基于Hash算法實(shí)現(xiàn)的窖张,其性能通常都優(yōu)于TreeSet。為快速查找而設(shè)計(jì)的Set蚁滋,我們通常都應(yīng)該使用HashSet宿接,在我們需要排序的功能時(shí)赘淮,我們才使用TreeSet。
使用 CopyOnWriteArrayList 和 CopyOnWriteArraySet
在對(duì)其實(shí)例進(jìn)行修改操作(add/remove等)會(huì)新建一個(gè)數(shù)據(jù)并修改睦霎,修改完畢之后梢卸,再將原來(lái)的引用指向新的數(shù)組。這樣副女,修改過(guò)程沒(méi)有修改原來(lái)的數(shù)組蛤高。也就沒(méi)有了ConcurrentModificationException錯(cuò)誤。
HashMap與TreeMap肮塞、HashTable的區(qū)別及適用場(chǎng)景
HashMap 非線程安全
HashMap:基于哈希表(散列表)實(shí)現(xiàn)襟齿。使用HashMap要求添加的鍵類明確定義了hashCode()和equals()[可以重寫hashCode()和equals()],為了優(yōu)化HashMap空間的使用枕赵,您可以調(diào)優(yōu)初始容量和負(fù)載因子。其中散列表的沖突處理主要分兩種位隶,一種是開放定址法拷窜,另一種是鏈表法。HashMap的實(shí)現(xiàn)中采用的是鏈表法涧黄。
TreeMap:非線程安全基于紅黑樹實(shí)現(xiàn)篮昧。TreeMap沒(méi)有調(diào)優(yōu)選項(xiàng),因?yàn)樵摌淇偺幱谄胶鉅顟B(tài)笋妥。
適用場(chǎng)景分析:
HashMap和HashTable:HashMap去掉了HashTable的contains方法懊昨,但是加上了containsValue()和containsKey()方法。HashTable同步的春宣,而HashMap是非同步的酵颁,效率上比HashTable要高。HashMap允許空鍵值月帝,而HashTable不允許躏惋。
HashMap:適用于Map中插入、刪除和定位元素嚷辅。
Treemap:適用于按自然順序或自定義順序遍歷鍵(key)簿姨。
(ps:其實(shí)我們工作的過(guò)程中對(duì)集合的使用是很頻繁的,稍加注意并總結(jié)積累一下,在面試的時(shí)候應(yīng)該會(huì)回答的很輕松)
五. concurrentHashmap原理,原子類簸搞。
ConcurrentHashMap作為一種線程安全且高效的哈希表的解決方案扁位,尤其其中的"分段鎖"的方案,相比HashTable的全表鎖在性能上的提升非常之大.
六. volatile原理
在《Java并發(fā)編程:核心理論》一文中趁俊,我們已經(jīng)提到過(guò)可見性域仇、有序性及原子性問(wèn)題,通常情況下我們可以通過(guò)Synchronized關(guān)鍵字來(lái)解決這些個(gè)問(wèn)題则酝,不過(guò)如果對(duì)Synchronized原理有了解的話殉簸,應(yīng)該知道Synchronized是一個(gè)比較重量級(jí)的操作闰集,對(duì)系統(tǒng)的性能有比較大的影響,所以般卑,如果有其他解決方案武鲁,我們通常都避免使用Synchronized來(lái)解決問(wèn)題。
而volatile關(guān)鍵字就是Java中提供的另一種解決可見性和有序性問(wèn)題的方案蝠检。對(duì)于原子性沐鼠,需要強(qiáng)調(diào)一點(diǎn),也是大家容易誤解的一點(diǎn):對(duì)volatile變量的單次讀/寫操作可以保證原子性的叹谁,如long和double類型變量饲梭,但是并不能保證i++這種操作的原子性,因?yàn)楸举|(zhì)上i++是讀焰檩、寫兩次操作憔涉。
七. 多線程的使用場(chǎng)景
使用多線程就一定效率高嗎? 有時(shí)候使用多線程并不是為了提高效率析苫,而是使得CPU能夠同時(shí)處理多個(gè)事件兜叨。
1).為了不阻塞主線程,啟動(dòng)其他線程來(lái)做好事的事情,比如APP中耗時(shí)操作都不在UI中做.
2).實(shí)現(xiàn)更快的應(yīng)用程序,即主線程專門監(jiān)聽用戶請(qǐng)求,子線程用來(lái)處理用戶請(qǐng)求,以獲得大的吞吐量.感覺這種情況下,多線程的效率未必高衩侥。 這種情況下的多線程是為了不必等待国旷, 可以并行處理多條數(shù)據(jù)。
比如JavaWeb的就是主線程專門監(jiān)聽用戶的HTTP請(qǐng)求茫死,然后啟動(dòng)子線程去處理用戶的HTTP請(qǐng)求跪但。
3).某種雖然優(yōu)先級(jí)很低的服務(wù),但是卻要不定時(shí)去做峦萎。
比如Jvm的垃圾回收屡久。
4.)某種任務(wù),雖然耗時(shí)骨杂,但是不耗CPU的操作時(shí)涂身,開啟多個(gè)線程,效率會(huì)有顯著提高搓蚪。
比如讀取文件蛤售,然后處理。 磁盤IO是個(gè)很耗費(fèi)時(shí)間妒潭,但是不耗CPU計(jì)算的工作悴能。 所以可以一個(gè)線程讀取數(shù)據(jù),一個(gè)線程處理數(shù)據(jù)雳灾∧穑肯定比一個(gè)線程讀取數(shù)據(jù),然后處理效率高谎亩。 因?yàn)閮蓚€(gè)線程的時(shí)候充分利用了CPU等待磁盤IO的空閑時(shí)間炒嘲。
八. JAVA常量池
Interger中的128(-128~127)
a.當(dāng)數(shù)值范圍為-128~127時(shí):如果兩個(gè)new出來(lái)Integer對(duì)象宇姚,即使值相同,通過(guò)“==”比較結(jié)果為false夫凸,但兩個(gè)對(duì)象直接賦值浑劳,則通過(guò)“==”比較結(jié)果為“true,這一點(diǎn)與String非常相似夭拌。
b.當(dāng)數(shù)值不在-128~127時(shí)魔熏,無(wú)論通過(guò)哪種方式,即使兩個(gè)對(duì)象的值相等鸽扁,通過(guò)“==”比較蒜绽,其結(jié)果為false;
c.當(dāng)一個(gè)Integer對(duì)象直接與一個(gè)int基本數(shù)據(jù)類型通過(guò)“==”比較桶现,其結(jié)果與第一點(diǎn)相同躲雅;
d.Integer對(duì)象的hash值為數(shù)值本身;
為什么是-128-127?
在Integer類中有一個(gè)靜態(tài)內(nèi)部類IntegerCache巩那,在IntegerCache類中有一個(gè)Integer數(shù)組吏夯,用以緩存當(dāng)數(shù)值范圍為-128~127時(shí)的Integer對(duì)象。
九. 簡(jiǎn)單介紹一下java中的泛型即横,泛型擦除以及相關(guān)的概念。
泛型是Java SE 1.5的新特性裆赵,泛型的本質(zhì)是參數(shù)化類型东囚,也就是說(shuō)所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù)。這種參數(shù)類型可以用在類战授、接口和方法的創(chuàng)建中页藻,分別稱為泛型類、泛型接口植兰、泛型方法份帐。 Java語(yǔ)言引入泛型的好處是安全簡(jiǎn)單。
在Java SE 1.5之前楣导,沒(méi)有泛型的情況的下废境,通過(guò)對(duì)類型Object的引用來(lái)實(shí)現(xiàn)參數(shù)的“任意化”,“任意化”帶來(lái)的缺點(diǎn)是要做顯式的強(qiáng)制類型轉(zhuǎn)換筒繁,而這種轉(zhuǎn)換是要求開發(fā)者對(duì)實(shí)際參數(shù)類型可以預(yù)知的情況下進(jìn)行的噩凹。對(duì)于強(qiáng)制類型轉(zhuǎn)換錯(cuò)誤的情況,編譯器可能不提示錯(cuò)誤毡咏,在運(yùn)行的時(shí)候才出現(xiàn)異常驮宴,這是一個(gè)安全隱患。
泛型的好處是在編譯的時(shí)候檢查類型安全呕缭,并且所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)和隱式的堵泽,提高代碼的重用率修己。
1、泛型的類型參數(shù)只能是類類型(包括自定義類)迎罗,不能是簡(jiǎn)單類型睬愤。
2、同一種泛型可以對(duì)應(yīng)多個(gè)版本(因?yàn)閰?shù)類型是不確定的)佳谦,不同版本的泛型類實(shí)例是不兼容的戴涝。
3、泛型的類型參數(shù)可以有多個(gè)钻蔑。
4啥刻、泛型的參數(shù)類型可以使用extends語(yǔ)句,例如<T extends superclass>咪笑。習(xí)慣上稱為“有界類型”可帽。
5、泛型的參數(shù)類型還可以是通配符類型窗怒。例如Class<?> classType = Class.forName("java.lang.String");
泛型擦除以及相關(guān)的概念
Java中的泛型基本上都是在編譯器這個(gè)層次來(lái)實(shí)現(xiàn)的映跟。在生成的Java字節(jié)碼中是不包含泛型中的類型信息的。使用泛型的時(shí)候加上的類型參數(shù)扬虚,會(huì)在編譯器在編譯的時(shí)候去掉努隙。這個(gè)過(guò)程就稱為類型擦除。
類型擦除引起的問(wèn)題及解決方法
1辜昵、先檢查荸镊,在編譯,以及檢查編譯的對(duì)象和引用傳遞的問(wèn)題
2堪置、自動(dòng)類型轉(zhuǎn)換
3躬存、類型擦除與多態(tài)的沖突和解決方法
4、泛型類型變量不能是基本數(shù)據(jù)類型
5舀锨、運(yùn)行時(shí)類型查詢
6岭洲、異常中使用泛型的問(wèn)題
7、數(shù)組(這個(gè)不屬于類型擦除引起的問(wèn)題)
9坎匿、類型擦除后的沖突
10盾剩、泛型在靜態(tài)方法和靜態(tài)類中的問(wèn)題