1. Integer與 ==
Integer one = 128;
Integer two = 128;
System.out.println(one == two);
Integer one = 100;
Integer two = 100;
System.out.printf(one == two);
問:上面兩種打印結(jié)果有何不同
答:Integer類型當(dāng)正整數(shù)小于128時是在內(nèi)存棧中創(chuàng)建值的隐砸,并講對象指向這個值,這樣在比較兩個棧引用時因為是同一地址引用兩者則相等髓堪。當(dāng)大于127時將會調(diào)用new Integer(),兩個整數(shù)對象地址引用不相等。因此第一種會打印false猪叙,第二種打印true恐锣。
2. 數(shù)組轉(zhuǎn)list
下圖代碼執(zhí)行為何出錯
public static void main(String[] args){
String[] array = new String[]{"張三","李四","王五"};
List<String> list = Arrays.asList(array);
list.add("孫六");
System.out.printf(list.size());
}
問:上圖代碼執(zhí)行為何出錯
答:因為數(shù)組轉(zhuǎn)換的列表其實不是arrayList,它是數(shù)組內(nèi)部定義的一種數(shù)據(jù)結(jié)構(gòu)類型污抬,本質(zhì)上還是數(shù)組而非列表汞贸,因此當(dāng)向了你報添加元素就會出現(xiàn)錯誤。
3.float精度丟失問題
兩個float類型數(shù)據(jù)相減會丟失精度印机,尾部會帶著長長的一串?dāng)?shù)字矢腻。
4. JAVA中實現(xiàn)多線程的幾種方式
繼承Thread
實現(xiàn)runable
實現(xiàn)Callable,重寫call()方法
Callable對象屬于Executor框架中的功能類射赛,Callable與Runnable接口類似多柑,但提供了比Runnable更強大的功能:
1.Callable可以在任務(wù)結(jié)束后提供一個返回值,Runnable無法提供
2.Callable中的call()方法可以拋出異常楣责,而Runnable的run()方法則不能
3.運行Callable可以拿到一個Future對象竣灌,F(xiàn)uture對象表示異步計算的結(jié)果,可以使用Future來監(jiān)視目標(biāo)線程調(diào)用call()方法的使用情況秆麸,當(dāng)調(diào)用Future的get()方法以獲取結(jié)果時初嘹,當(dāng)前線程會阻塞,知道call方法結(jié)束返回結(jié)果為止沮趣。
5.序列化
問:什么情況下需要序列化屯烦,RPC服務(wù)中的參數(shù)為啥都需要序列化,參數(shù)中的日期參數(shù)類型到底用sql.Date還是util.Date房铭?
答:序列化的目的是依賴為了進(jìn)行網(wǎng)絡(luò)傳輸驻龟,確保傳過去的字節(jié)流還能被反編譯找到對應(yīng)的類,二來是為了方便本地硬盤存儲缸匪。RPC服務(wù)為異步服務(wù)都是通過網(wǎng)絡(luò)傳輸數(shù)據(jù)翁狐,當(dāng)然需要序列化數(shù)據(jù)。Java.sql.Date類繼承java.util.Date類凌蔬,但是并未實現(xiàn)序列化因此作為參數(shù)不能再RPC服務(wù)中心傳輸露懒。
6.final關(guān)鍵字修飾一個變量時闯冷,是引用不能變,還是引用的對象不能變隐锭?
答:使用final關(guān)鍵字修飾一個變量時窃躲,是指引用變量不能變,引用變量所指向的對象中的內(nèi)容還是可以改變的钦睡。例
final StringBuffer a = new StringBuffer("immutable");
執(zhí)行如下語句將提示錯誤
a = new StringBuffer("");
但執(zhí)行如下語句則可以通過編譯
a.append("broken!");
有人在定義方法的參數(shù)時蒂窒,可能想采用如下形式來阻止方法內(nèi)部修改傳進(jìn)來的參數(shù)對象:
public void method(final StringBuffer param){}
實際上這是辦不到的,在該方法內(nèi)部仍然可以增加如下代碼來修改參數(shù)對象:
param.append("a");
7.抽象類與普通類的區(qū)別
抽象類與普通類的唯一區(qū)別就是不能創(chuàng)建實例對象和允許有abstract方法荞怒。
8.Collection和Collections的區(qū)別
Collection是集合類的上級接口洒琢,繼承他的接口主要有Set和List
Collections是針對集合類的一個幫助類,他提供一系列靜態(tài)方法實現(xiàn)對各種集合的搜索褐桌、排序衰抑、線程安全等操作。
9.final荧嵌、finally呛踊、finalize的區(qū)別
final用于聲明屬性、方法和類啦撮,分別表示屬性不可變谭网,方法不可覆蓋,類不能被繼承赃春。內(nèi)部類要訪問局部變量愉择,局部變量必須定義成final類型。
finally是異常處理語句結(jié)構(gòu)的一部分织中,表示總是執(zhí)行锥涕。
finalize是Object類的一個方法,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法狭吼,可以覆蓋此方法提供垃圾收集時的其他資源回收层坠,但是JVM不保證此方法總被調(diào)用。
10.wait和sleep的區(qū)別
1.歸屬不同:sleep()方法屬于Thread類刁笙,而wait()方法破花,則是屬于Object類;
2.sleep()方法導(dǎo)致了程序暫停執(zhí)行指定的時間采盒,讓出cpu給其他線程旧乞,但是他的監(jiān)控狀態(tài)依然保持著蔚润,當(dāng)指定的時間到了又會自動恢復(fù)運行狀態(tài)磅氨。所以在調(diào)用sleep()方法的過程中,線程不會釋放對象鎖嫡纠。
3.調(diào)用wait()方法的時候烦租,線程會放棄對象鎖延赌,進(jìn)入等待此對象的等待鎖定池,只有針對此對象調(diào)用notify()方法后線程才進(jìn)入對象鎖定池準(zhǔn)備獲取對象鎖進(jìn)行入運行狀態(tài)叉橱。
11.springmvc的核心是什么挫以,請求的流程時怎么處理的,控制反轉(zhuǎn)怎么實現(xiàn)窃祝?
核心:控制反轉(zhuǎn)和面向切面
請求處理流程:
1.首先用戶發(fā)送請求到前段控制器掐松,前端控制器根據(jù)請求信息(如URL)老決定選擇哪一個頁面控制器進(jìn)行處理并發(fā)請求委托給它。
2.頁面控制器接收到請求后粪小,進(jìn)行功能處理大磺,首先需要收集和綁定請求參數(shù)到一個對象,并進(jìn)行驗證探膊,然后將命令對象委托給業(yè)務(wù)對象進(jìn)行處理杠愧;處理完畢返回一個ModelAndView(模型數(shù)據(jù)和邏輯視圖名);
3.前端控制器收回控制權(quán)逞壁,然后根據(jù)返回的邏輯視圖名流济,選擇相應(yīng)的視圖進(jìn)行渲染,并把模型數(shù)據(jù)傳入以便視圖渲染腌闯;
4.前端控制器再次回收控制權(quán)绳瘟,將相應(yīng)返回給客戶。
控制反轉(zhuǎn)如何實現(xiàn):
我們每次使用spring框架都要配置xml文件绑嘹,這個xml配置了bean的id和class稽荧。spring中默認(rèn)的bean為單實例模式,通過bean的class引用反射機制可以創(chuàng)建這個實例工腋。
因此姨丈,spring框架通過反射替我們創(chuàng)建好了實例并且替我們維護他們。
A需要引用B類擅腰,spring框架就會通過xml把B實例的引用傳給了A的成員變量蟋恬。
12.mybatis如何處理結(jié)果集
MyBatis的結(jié)果集是通過反射來實現(xiàn)的。并不是通過get/set方法趁冈。在實體類中無論是否定義get/set()方法歼争,都是可以接受到的。
13.JAVA中堆和棧渗勘,分別是什么數(shù)據(jù)結(jié)構(gòu)沐绒,為什么要分堆和棧來存儲數(shù)據(jù)?
棧是一種具有后進(jìn)先出性質(zhì)的數(shù)據(jù)結(jié)構(gòu)旺坠。堆是一種經(jīng)過排序的樹形數(shù)據(jù)結(jié)構(gòu)乔遮。通常所說的堆的數(shù)據(jù)結(jié)構(gòu)是指二叉堆。堆的特點是根節(jié)點的值最小(或最大)取刃,且根節(jié)點的兩個字?jǐn)?shù)也是一個堆蹋肮。
為什么分堆和棧:1.從軟件設(shè)計角度看出刷,棧代表了處理邏輯,而堆代表了數(shù)據(jù)坯辩。這樣分開馁龟,使得處理邏輯更為清晰。2.堆與棧的分離漆魔,使得堆中的內(nèi)容可以被多個棧共享坷檩。一方面這種共享提供了一種有效的數(shù)據(jù)交互方式,另一方面改抡,堆中的共享常量和緩存可以被所有棧訪問淌喻,節(jié)省了空間。3.棧棧因為運行的需要雀摘,比如保存系統(tǒng)運行的上下文裸删,需要進(jìn)行地址段的劃分。由于棧只能向上增長阵赠,因此就會限制住棧存儲內(nèi)容的能力涯塔。而堆不同,堆中的對象可以根據(jù)需要動態(tài)增長的清蚀,因為棧和堆的拆分匕荸,是的動態(tài)增長成為可能,相應(yīng)棧中只需要記錄堆中的一個地址即可枷邪。4.體現(xiàn)了JAVA面向?qū)ο筮@一核心特點榛搔。
14.mysql優(yōu)化經(jīng)驗
1.對查詢進(jìn)行優(yōu)化,應(yīng)盡量避免全表掃描东揣,首先應(yīng)考慮在where及order by涉及的列上建立索引
2.應(yīng)盡量避免在where子句中使用!=或<>操作符践惑,否則引擎將放棄使用索引而進(jìn)行全表掃描。
3.盡量使用數(shù)字型字段嘶卧,若只含數(shù)值信息的字段盡量不要設(shè)計為字符型尔觉,這樣會降低查找和連接的性能,并會增加存儲開銷芥吟。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符侦铜,而對于數(shù)字型而言只需要比較一次就夠了吉懊。
4.任務(wù)地方都不要使用select * from t,用具體的字段列表代替“*”磁浇,不要返回用不到的任務(wù)字段窥突。
5.避免頻繁創(chuàng)建和刪除臨時表返帕,以減少系統(tǒng)表資源的消耗。
15.Spring的核心模塊
☆ Spring Core【核心容器】:核心容器提供了Spring的基本功能串远。核心容器的核心功能是用IOC容器來管理類的依賴關(guān)系
☆Spring AOP【面向切面】:Spring的AOP模塊提供了面向切面編程的支持创泄。Spring AOP采用的是純JAVA實現(xiàn)沪蓬,采用基于代理的AOP實現(xiàn)方案,AOP代理有IOC容器負(fù)責(zé)生成羞秤,管理,依賴關(guān)系也一并有IOC容器管理左敌。
☆Spring ORM【對象試題映射】:提供了與多個第三方持久層框架的良好整合瘾蛋。
☆Spring DAO【持久層模塊】:Spring進(jìn)一步簡化DAO開發(fā)步驟,能以一致的的方式使用數(shù)據(jù)庫訪問技術(shù)矫限,用統(tǒng)一的方式調(diào)用事務(wù)管理哺哼,避免具體的實現(xiàn)侵入業(yè)務(wù)邏輯層的代碼中。
☆Spring Context【應(yīng)用上下文】:它是一個配置文件叼风,為Spring提供上下文信息取董,提供了框架式的對象訪問方法。
Spring Web【W(wǎng)eb模塊】:提供了基礎(chǔ)的針對Web開發(fā)的集成特性无宿。
☆Spring MVC【MVC模塊】:提供了Web應(yīng)用的MVC實現(xiàn)茵汰。Spring的MVC框架并不是僅僅提供一種傳統(tǒng)的實現(xiàn),它提供了一種清晰的分離模型孽鸡。
16 redis常用的五種數(shù)據(jù)類型
1.String(字符串)蹂午、2.Hash(哈希)、3.List(列表)彬碱、4.set(集合)豆胸、5.zset(有序集合)
17 進(jìn)程間的通信方式
☆pipe【管道】
☆popen【高級管道】
☆named pipe【有名管道】
☆MessageQueue【消息隊列】
☆SHaredMemory【共享存儲】
☆Semaphore【信號量】
☆Socket【套接字】
☆sinal【信號】
17.堆內(nèi)存分類
目前大部分JVM采用“分帶收集算法”,所謂分帶收集就是根據(jù)對象的生命周期把內(nèi)存分為幾塊巷疼,一般把堆分為年輕代晚胡、年老代、持久代(1.8之后有空間取代)嚼沿。分配比例為:年輕代:年老代 = 1 :2
年輕代:“朝生夕死”估盘,存活率低,使用復(fù)制算法骡尽》揲荩可劃分為三個區(qū)域:原始區(qū)(Eden)和兩個小的存活區(qū)(Survivor),兩個存活區(qū)按功能分為From和To爆阶。絕大多數(shù)對象都在原始區(qū)分配燥透,超過一個垃圾回收操作仍然存活的對象放到存活區(qū)。垃圾回收絕大部分發(fā)生在年輕代辨图。
年老代:存活率高班套,使用“標(biāo)記-清楚”或“標(biāo)記-整理”算法。存儲年輕代中經(jīng)過多個回收周期仍然存活的對象故河,對于一些大的內(nèi)存分配吱韭,也可能會直接分配到年老代。
持久代:存儲類、方法以及它們的描述信息理盆。注:1.8之后再無持久代而是用元空間代替痘煤,元空間不存在虛擬機中而是在本地內(nèi)存。
18 堆 年輕代
年輕代可分三區(qū):Eden猿规、SurvivorFrom衷快、SurvivorTo。默認(rèn)劃分比例 8:1:1
GC過程:Eden區(qū)滿觸發(fā)Minor GC 將還活著的對象拷貝至SurvivorFrom區(qū)姨俩,當(dāng)Eden再次觸發(fā)GC時掃描Eden區(qū)和From區(qū)蘸拔,將存活的對象復(fù)制至To區(qū),同時對象年齡+1环葵。完成復(fù)制后清空Eden區(qū)和From區(qū)调窍。此時清空的From區(qū)和To區(qū)發(fā)生交換。即始終保持To區(qū)為空张遭,原To去變?yōu)橄乱淮蜧C的From區(qū)邓萨。部分對象在From和To中來回復(fù)制,如此當(dāng)對象年齡>某數(shù)值(JVM參數(shù)可設(shè))時菊卷,將還在存活的對象放入年老代先誉。
19 堆 年老代
年老代存儲存活比較久的對象或者是大對象。
GC過程 年老代GC是采用標(biāo)記清除算法的烁,當(dāng)堆中有效內(nèi)存被耗盡時褐耳,它會讓整個程序stop然后進(jìn)行標(biāo)記在清除。
標(biāo)記:標(biāo)記的過程其實就是渴庆,遍歷所有的GC Roots铃芦,然后將所有的GC Roots可達(dá)的對象標(biāo)記為存活對象。
清除:遍歷堆中所有對象中沒有標(biāo)記的對象全部清除掉
缺點-1:效率比較低(遞歸與全堆對象遍歷)襟雷,而且在進(jìn)行GC的時候刃滓,需要停止應(yīng)用程序。
缺點-2:清理出的內(nèi)存不連續(xù)耸弄,JVM就不得不維持一個內(nèi)存的空閑列表咧虎,這又是一個開銷
標(biāo)記-整理:首先標(biāo)記所有需要回收的對象,讓所有存活的對象都向一段移動计呈,然后直接清理掉邊界意外的內(nèi)存砰诵。
優(yōu)點:不會產(chǎn)生空間碎片,但整理需要一點時間捌显;
適用:適合年老代進(jìn)行垃圾收集茁彭,parallel Old gc 和Serial old就是采用的標(biāo)記-整理。
20 復(fù)制回收算法扶歪、標(biāo)記清除算法
復(fù)制回收算法-優(yōu)點:在存活對象不多的情況下理肺,性能高,可解決內(nèi)存碎片和標(biāo)記清除算法中導(dǎo)致的引用更新問題。
缺點:會造成內(nèi)存浪費妹萨,可根據(jù)實際情況調(diào)整內(nèi)存塊大小比例年枕。但是如果存活對象的數(shù)量比較大,coping的性能也會變的很差乎完。
21.垃圾回收
Minor GC:從年輕代空間回收內(nèi)存熏兄,復(fù)制算法
Major GC:老年代GC
Full GC:Full GC是對整個堆來說的。標(biāo)記清除算法
觸發(fā)Full GC的條件
1.System.gc() 建議jvm執(zhí)行full gc 并不一定執(zhí)行
2.執(zhí)行了jmap -histo:live pid命令 立即觸發(fā)Full GC
3.使用了大對象 大對象會直接進(jìn)入老年代
4.在程序中長期持有對象的引用 //對象年齡達(dá)到指定閾值也會進(jìn)入老年代
5.執(zhí)行minor gc時進(jìn)行一系列檢查:如下
a.執(zhí)行Minor GC的時候囱怕,JVM會檢查老年代中最大連續(xù)可用空間是否大于了當(dāng)前新生代所有對象的總大小。
b.如果大于毫别,則直接執(zhí)行Minor GC(這個時候執(zhí)行是沒有風(fēng)險的)娃弓。
c.如果小于了,JVM會檢查是否開啟了空間分配擔(dān)保機制岛宦,如果沒有開啟則直接改為執(zhí)行Full GC台丛。
d.如果開啟了,則JVM會檢查老年代中最大連續(xù)可用空間是否大于了歷次晉升到老年代中的平均大小砾肺,如果小于則執(zhí)行改為執(zhí)行Full GC挽霉。
e.如果大于則會執(zhí)行Minor GC,如果Minor GC執(zhí)行失敗則會執(zhí)行Full GC
33.Quartz任務(wù)調(diào)度框架
定義:Quatz是一個完全由Java編寫的開源任務(wù)框架变汪,通過觸發(fā)器設(shè)置作業(yè)定時運行時間侠坎,控制作業(yè)的運行時間。
集群:Quatz集群通過故障切換和負(fù)載平衡的功能裙盾,能給調(diào)度器帶來高可用性和伸縮性实胸。
功能:主要用來執(zhí)行定時任務(wù),如:定時發(fā)送消息番官、定時生成報表等庐完。
核心組件:調(diào)度器(scheduler)、觸發(fā)器(trigger)徘熔、工作(JobDetail)
??調(diào)度器(scheduler):一個調(diào)度器可以注冊眾多的觸發(fā)器和工作门躯,調(diào)度器啟動后,里面的每個工作會根據(jù)調(diào)度器按部就班的自動執(zhí)行
??觸發(fā)器(trigger):代表調(diào)度參數(shù)的配置酷师,什么時候去調(diào)工作
??工作(JobDetail):一個可執(zhí)行的作業(yè)讶凉,它本身可能是有狀態(tài)的。
工作過程:當(dāng)JobDetail和Trigger在scheduler容器上注冊后山孔,形成了裝配好的作業(yè)(JobDetail和Trigger組成一對兒)缀遍,就可以伴隨容器啟動而調(diào)度執(zhí)行了。scheduler是個容器饱须,容器中有一個線程池域醇,用來并行調(diào)度執(zhí)行每個作業(yè),這樣可以提供容器效率。
優(yōu)缺點:
??quartz作為組件可嵌入任務(wù)獨立的系統(tǒng)中運行
??quartz可在應(yīng)用服務(wù)器或者servlet容器中實例化
??quartz可獨立運行在本身所帶的虛擬機中
??quartz可以被實例化獨立項目的集群(有負(fù)載均衡和容錯能力)
Quartz與spring自帶定時器(Timer Task)的差別:
??精確度:Quartz可通過cron表達(dá)式精確到特定的時間執(zhí)行譬挚,而TimerTask不行锅铅。
??任務(wù)數(shù)量:Quartz每次執(zhí)行都會創(chuàng)建一個新的任務(wù)對象,但TimerTash則每次都使用同一個任務(wù)類對象减宣。
??異常處理:Quartz執(zhí)行異常時盐须,不會影響下一次任務(wù)的執(zhí)行;但TimerTask不同漆腌,一旦某個任務(wù)在執(zhí)行過程中拋出異常贼邓,則整個定時器生命周期就結(jié)束,不會再執(zhí)行定時任務(wù)闷尿。
34.什么是一致性Hash算法塑径?
一致性hash是為了解決分布式而提出的。在動態(tài)變化的分布式環(huán)境中判斷Hash算法好壞的主要有四個方面:平衡性填具、單調(diào)性统舀、分散性、負(fù)載
環(huán)形Hash空間
??按照常用的Hash算法將對應(yīng)的值哈希到一個具有2^32次方個桶的空間中劳景,即0 ~ (2^32)- 1的數(shù)字空間誉简,將這些數(shù)字首尾相連形成一個閉合的環(huán)形。
數(shù)據(jù)映射
??將對象通過特定的Hash函數(shù)計算出對應(yīng)的key盟广,然后散列到hash環(huán)上
設(shè)備映射
??將設(shè)備通過特定Hash算法計算出對應(yīng)的key闷串,并散列到Hash換上,然后以順時針方向計算筋量,將所有對象存儲到離自己最近的機器中去窿克。這樣在面對機器個數(shù)發(fā)生改變時,只會有一小部分的數(shù)據(jù)的存儲位置需要發(fā)生改變
解決平衡問題
上述算法存在一個問題毛甲,即當(dāng)存儲設(shè)備過少時極有可能造成數(shù)據(jù)分配不平衡年叮。為了解決這種問題,引入了虛擬節(jié)點玻募。所謂虛擬節(jié)點是實際節(jié)點(機器)在hash空間的復(fù)制品只损。一個實際節(jié)點對對應(yīng)若干個虛擬節(jié)點,這個對應(yīng)個數(shù)也稱為“復(fù)制個數(shù)”七咧,虛擬節(jié)點在hash環(huán)空間中以hash值排列跃惫。
虛擬節(jié)點
??虛擬節(jié)點的hash計算可以采用對應(yīng)節(jié)點的IP地址加數(shù)字后綴的方式
詳情解讀: https://www.cnblogs.com/myseries/p/10956835.html
35. maven優(yōu)勢
Maven是JAVA平臺下的一款項目構(gòu)建和依賴管理的自動化工具
優(yōu)點:
??1. 自動導(dǎo)入jar及其依賴;
??2. maven支持插件可實現(xiàn)配置文件管理艾栋;根據(jù)環(huán)境的不同加載不同的配置文件
??3. 實現(xiàn)項目多模塊化爆存;讓每個模塊獨立,高內(nèi)聚蝗砾,低耦合先较,不同的模塊之間保持自己的完整性携冤,可以互不干擾,方便以后的維護開發(fā)闲勺。
??4. 生命周期管理曾棕,自動完成工程的基礎(chǔ)構(gòu)建配置。