原文鏈接:https://mp.weixin.qq.com/s/wQIG8k2m0RAuChhiWTWzlQ
基于我個(gè)人對(duì)面試的認(rèn)知和招聘經(jīng)驗(yàn)缺猛,在此我總結(jié)一下Java開(kāi)發(fā)者的基礎(chǔ)知識(shí)掌握要求萌腿,及應(yīng)聘者面試的需要準(zhǔn)備的內(nèi)容。
首先,Java基礎(chǔ)是每個(gè)面試官都會(huì)問(wèn)到的诽凌,可能只是針對(duì)工作經(jīng)驗(yàn)的多少,對(duì)問(wèn)題追蹤深度有所差異坦敌÷滤校基本對(duì)初中級(jí)開(kāi)發(fā)者來(lái)說(shuō)痢法,基礎(chǔ)理論和應(yīng)用不可缺少。對(duì)中高級(jí)杜顺,面試官會(huì)基于基礎(chǔ)理論問(wèn)一些底層的原理甚至對(duì)源碼的理解财搁。
一、JVM及工作原理
JVM --- Java Virtual Machine躬络,即Java虛擬機(jī)尖奔。大家都知道Java具有可跨平臺(tái)特性,其主要是指字節(jié)碼(.class文件)可以在任何具有Java虛擬機(jī)的計(jì)算機(jī)上運(yùn)行穷当,Java虛擬機(jī)中的Java解釋器負(fù)責(zé)將字節(jié)碼文件解釋成為特定的機(jī)器碼進(jìn)行運(yùn)行提茁。JVM的體系結(jié)構(gòu)分為三部分,分別是:類(lèi)加載器(ClassLoader)馁菜,運(yùn)行時(shí)數(shù)據(jù)區(qū)和執(zhí)行引擎茴扁。
1、類(lèi)加載器:在JVM啟動(dòng)時(shí)或者在類(lèi)運(yùn)行時(shí)將需要的,class加載到JVM中汪疮。
2峭火、運(yùn)行時(shí)數(shù)據(jù)區(qū):是在JVM運(yùn)行的時(shí)候操作所分配的內(nèi)存區(qū),主要?jiǎng)澐譃?個(gè)區(qū)域:
方法區(qū)(Method Area):用于存儲(chǔ)類(lèi)結(jié)構(gòu)信息的地方智嚷,包括常量池卖丸、靜態(tài)變量、構(gòu)造函數(shù)等纤勒。
Java堆(Heap):存儲(chǔ)java實(shí)例或者對(duì)象的地方坯苹,也是GC的主要區(qū)域。
Java棧(Stack):java椧√欤總是和線程關(guān)聯(lián)在一起粹湃,每當(dāng)創(chuàng)建一個(gè)線程時(shí),JVM就會(huì)為這個(gè)線程創(chuàng)建一個(gè)對(duì)應(yīng)的java棧泉坐。
程序計(jì)數(shù)器(PC Register):用于保存當(dāng)前線程執(zhí)行的內(nèi)存地址为鳄。
本地方法棧(Native Method Stack):和java棧的作用差不多,只不過(guò)是為JVM使用到的native方法服務(wù)的
3腕让、執(zhí)行引擎:負(fù)責(zé)執(zhí)行class文件中包含的字節(jié)碼指令孤钦。
二、java垃圾回收機(jī)制
在java中纯丸,程序員是不需要去釋放一個(gè)對(duì)象的內(nèi)存的偏形,而是由虛擬機(jī)自行執(zhí)行。在JVM中觉鼻,有一個(gè)垃圾回收線程俊扭,它是低優(yōu)先級(jí)的,在正常情況下是不會(huì)執(zhí)行坠陈,只有在虛擬機(jī)空閑或者當(dāng)前堆內(nèi)存不足時(shí)萨惑,才會(huì)觸發(fā)執(zhí)行捐康,掃描那些沒(méi)有被任何引用的對(duì)象,并將它們添加到要回收的集合中進(jìn)行回收庸蔼。
垃圾回收算法:
- 標(biāo)記-清除
- 標(biāo)記-復(fù)制
- 標(biāo)記-整理
- 分代回收
哪些對(duì)象應(yīng)該被回收:
這就要從對(duì)象存活性判斷解总,常用的方法有兩種:1.引用計(jì)數(shù)法;2.對(duì)象可達(dá)性分析姐仅。由于引用計(jì)數(shù)法存在互相引用導(dǎo)致無(wú)法進(jìn)行GC的問(wèn)題花枫,所以目前JVM虛擬機(jī)多使用對(duì)象可達(dá)性分析算法。
三掏膏、接口和抽象類(lèi)的區(qū)別
默認(rèn)方法:抽象類(lèi)可以有默認(rèn)的方法實(shí)現(xiàn)乌昔,接口中不存在方法的實(shí)現(xiàn)。
實(shí)現(xiàn)方式:子類(lèi)使用extends關(guān)鍵字來(lái)繼承抽象類(lèi)壤追,如果子類(lèi)不是抽象類(lèi)磕道,子類(lèi)需要提供抽象類(lèi)中所聲明方法的實(shí)現(xiàn)。而接口的子類(lèi)使用implements來(lái)實(shí)現(xiàn)接口行冰,需要提供接口中所有聲明的實(shí)現(xiàn)溺蕉。
構(gòu)造函數(shù):抽象類(lèi)中可以有構(gòu)造函數(shù),接口中不能悼做。
和正常類(lèi)區(qū)別:抽象類(lèi)不能被實(shí)例化疯特,接口則是完全不同的類(lèi)型。
訪問(wèn)修飾符:抽象方法可以有public,protected和default等修飾肛走,接口默認(rèn)是public漓雅,不能使用其他修飾符。
多繼承:一個(gè)子類(lèi)只能繼承在一個(gè)抽象類(lèi)朽色,而一個(gè)子類(lèi)可以實(shí)現(xiàn)多個(gè)接口邻吞。
添加新方法:想在抽象類(lèi)中添加新方法,可以提供默認(rèn)的實(shí)現(xiàn)葫男,因此可以不修改子類(lèi)現(xiàn)有的代碼抱冷。如果往接口中添加新方法,則子類(lèi)中需要實(shí)現(xiàn)該方法梢褐。
四旺遮、String相關(guān)問(wèn)題
String相關(guān)問(wèn)題很常見(jiàn),對(duì)初級(jí)開(kāi)發(fā)者來(lái)說(shuō)盈咳,String的基礎(chǔ)使用方法必須掌握耿眉。
1、Strings=new String(“xyz”) 創(chuàng)建了幾個(gè)String Object?
兩個(gè)或一個(gè)鱼响,”xyz”對(duì)應(yīng)一個(gè)對(duì)象鸣剪,這個(gè)對(duì)象放在字符串常量緩沖區(qū),常量”xyz”不管出現(xiàn)多少遍,都是緩沖區(qū)中的那一個(gè)西傀。New String每寫(xiě)一遍,就創(chuàng)建一個(gè)新的對(duì)象桶癣,它一句那個(gè)常量”xyz”對(duì)象的內(nèi)容來(lái)創(chuàng)建出一個(gè)新String對(duì)象拥褂。如果以前就用過(guò)’xyz’,這句代表就不會(huì)創(chuàng)建”xyz”自己了牙寞,直接從緩沖區(qū)拿饺鹃。
2、String與StringBuffer及StringBuilder的區(qū)別
它們都可以儲(chǔ)存和操作字符串间雀,即包含多個(gè)字符的字符數(shù)據(jù)悔详,主要區(qū)別:
String類(lèi)表示內(nèi)容不可改變的字符串,而StringBuffer和StringBuilder類(lèi)都表示內(nèi)容可以被修改的字符串惹挟。
String實(shí)現(xiàn)了equals方法茄螃,new String(“abc”).equals(new String(“abc”)的結(jié)果為true。而StringBuffer和StringBuilder沒(méi)有實(shí)現(xiàn)equals方法连锯,所以归苍,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的結(jié)果為false。
3运怖、StringBuffer與StringBuilder的區(qū)別
StringBuffer和StringBuilder都表示內(nèi)容可以被修改的字符串拼弃,StringBuffer是線程安全的,而StringBuilder是線程不安全的摇展,它相比StringBuffer運(yùn)行效率高吻氧。如果一個(gè)字符串變量是在方法里面定義,這種情況只可能有一個(gè)線程訪問(wèn)它咏连,不存在不安全因素了盯孙,則用StringBuilder。如果要在類(lèi)里面定義成員變量祟滴,并且這個(gè)類(lèi)的實(shí)例對(duì)象會(huì)在多線程環(huán)境下使用镀梭,那么最好用StringBuffer。
五踱启、線程报账、進(jìn)程相關(guān)
1、線程和進(jìn)程的區(qū)別
簡(jiǎn)而言之埠偿,進(jìn)程是程序運(yùn)行和資源分配的基本單位透罢,一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程冠蒋。進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存單元羽圃,而多個(gè)線程共享內(nèi)存資源,減少切換次數(shù)抖剿,從而效率更高朽寞。線程是進(jìn)程的一個(gè)實(shí)體识窿,是cpu調(diào)度和分派的基本單位,是比程序更小的能獨(dú)立運(yùn)行的基本單位脑融。同一進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行喻频。
2、如何創(chuàng)建線程肘迎,他們有什么區(qū)別?
創(chuàng)建線程可以實(shí)現(xiàn)java.lang.Runnable或者通過(guò)繼承java.lang.Thread類(lèi)兩種方法甥温。這兩種方法的區(qū)別:
1)Java不支持多繼承。因此擴(kuò)展Thread類(lèi)就代表這個(gè)子類(lèi)不能擴(kuò)展其他類(lèi)妓布。而實(shí)現(xiàn)Runnable接口的類(lèi)還可能擴(kuò)展另一個(gè)類(lèi)姻蚓。
2)類(lèi)可能只要求可執(zhí)行即可,因此繼承整個(gè)Thread類(lèi)的開(kāi)銷(xiāo)過(guò)大匣沼。
3狰挡、Thread的start()和run()方法的區(qū)別?
start()方法被用來(lái)啟動(dòng)新創(chuàng)建的線程释涛,而且start()內(nèi)部調(diào)用了run()方法圆兵,這和直接調(diào)用run()方法的效果不一樣。當(dāng)你調(diào)用run()方法的時(shí)候枢贿,只會(huì)是在原來(lái)的線程中調(diào)用殉农,沒(méi)有新的線程啟動(dòng),start()方法才會(huì)啟動(dòng)新線程局荚。
4超凳、wait()和sleep()方法的區(qū)別?
1)sleep()來(lái)自Thread類(lèi)耀态,和wait()來(lái)自O(shè)bject類(lèi)轮傍。調(diào)用sleep()方法的過(guò)程中,線程不會(huì)釋放對(duì)象鎖首装。而 調(diào)用 wait 方法線程會(huì)釋放對(duì)象鎖创夜;
2)sleep()睡眠后不出讓系統(tǒng)資源,wait讓其他線程可以占用CPU仙逻;
3)sleep(milliseconds)需要指定一個(gè)睡眠時(shí)間驰吓,時(shí)間一到會(huì)自動(dòng)喚醒,而wait()需要配合notify()或者notifyAll()使用系奉;
5檬贰、什么導(dǎo)致線程阻塞,怎么喚醒一個(gè)已經(jīng)阻塞的線程缺亮?
線程阻塞指的是暫停一個(gè)線程的執(zhí)行以等待某個(gè)條件發(fā)生翁涤。Java 提供了大量方法來(lái)支持阻塞,下面讓我們逐一分析。
1)sleep() 允許指定以毫秒為單位的一段時(shí)間作為參數(shù)葵礼,它使得線程在指定的時(shí)間內(nèi)進(jìn)入阻塞狀態(tài)号阿,指定的時(shí)間一過(guò),線程重新進(jìn)入可執(zhí)行狀態(tài)鸳粉。
2)suspend()和resume() 這兩個(gè)方法配套使用扔涧,suspend()使得線程進(jìn)入阻塞狀態(tài),并且不會(huì)自動(dòng)恢復(fù)赁严,必須其對(duì)應(yīng)的resume() 被調(diào)用,才能使得線程重新進(jìn)入可執(zhí)行狀態(tài)粉铐。
3)yield() 使當(dāng)前線程放棄當(dāng)前已經(jīng)分得的CPU 時(shí)間疼约,但不使當(dāng)前線程阻塞,即線程仍處于可執(zhí)行狀態(tài)蝙泼,隨時(shí)可能再次分得 CPU 時(shí)間程剥。
4)wait()和notify() 這兩個(gè)方法配套使用,wait() 使得線程進(jìn)入阻塞狀態(tài)汤踏,它有兩種形式织鲸,一種允許指定以毫秒為單位的一段時(shí)間作為參數(shù),另一種沒(méi)有參數(shù)溪胶,前者當(dāng)對(duì)應(yīng)的 notify() 被調(diào)用或者超出指定時(shí)間時(shí)線程重新進(jìn)入可執(zhí)行狀態(tài)搂擦,后者則必須對(duì)應(yīng)的 notify() 被調(diào)用。
喚醒阻塞線程:如果線程是因?yàn)檎{(diào)用了wait()哗脖、sleep()或者join()方法而導(dǎo)致的阻塞瀑踢,可以中斷線程,并且通過(guò)拋出InterruptedException來(lái)喚醒它才避;如果線程遇到了IO阻塞橱夭,無(wú)能為力,因?yàn)镮O是操作系統(tǒng)實(shí)現(xiàn)的桑逝,Java代碼并沒(méi)有辦法直接接觸到操作系統(tǒng)棘劣。
6、產(chǎn)生死鎖的條件
1)互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用楞遏。
2)請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí)茬暇,對(duì)已獲得的資源保持不放。
3)不剝奪條件:進(jìn)程已獲得的資源寡喝,在末使用完之前而钞,不能強(qiáng)行剝奪。
4)循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系拘荡。
7臼节、線程鎖(ThreadLocal)的作用
簡(jiǎn)單說(shuō)ThreadLocal就是一種以空間換時(shí)間的做法,在每個(gè)Thread里面維護(hù)了一個(gè)ThreadLocal.ThreadLocalMap把數(shù)據(jù)進(jìn)行隔離,數(shù)據(jù)不共享网缝,自然就沒(méi)有線程安全方面的問(wèn)題了巨税。
8、樂(lè)觀鎖與悲觀鎖
樂(lè)觀鎖:樂(lè)觀鎖認(rèn)為競(jìng)爭(zhēng)不總是會(huì)發(fā)生粉臊,因此它不需要持有鎖草添,將比較、替換這兩個(gè)動(dòng)作作為一個(gè)原子操作嘗試去修改內(nèi)存中的變量扼仲,如果失敗則表示發(fā)生沖突远寸,那么就應(yīng)該有相應(yīng)的重試邏輯。
悲觀鎖:它競(jìng)爭(zhēng)總是會(huì)發(fā)生屠凶,因此每次對(duì)某資源進(jìn)行操作時(shí)驰后,都會(huì)持有一個(gè)獨(dú)占的鎖,就像synchronized矗愧,不管其他灶芝,直接上了鎖就操作資源了。
六唉韭、JAVA集合
關(guān)于Java中的集合體系是每個(gè)人都應(yīng)該爛熟于心的夜涕,尤其是對(duì)我們經(jīng)常使用的List、Set属愤、Map的原理更該如此女器。
1、集合與數(shù)組的區(qū)別住诸?
1)數(shù)組是固定長(zhǎng)度的晓避,集合可變長(zhǎng)度的;
2)數(shù)組可以存儲(chǔ)基本數(shù)據(jù)類(lèi)型只壳,也可以存儲(chǔ)引用數(shù)據(jù)類(lèi)型俏拱。集合只能存儲(chǔ)引用數(shù)據(jù)類(lèi)型;
3)數(shù)組存儲(chǔ)的元素必須是同一個(gè)數(shù)據(jù)類(lèi)型吼句,而集合存儲(chǔ)的對(duì)象可以是不同數(shù)據(jù)類(lèi)型锅必;
2、Java集合的層次關(guān)系
如圖所示惕艳,圖中實(shí)線邊框的是實(shí)現(xiàn)類(lèi)搞隐,折線邊框的是抽象類(lèi),點(diǎn)線的是接口远搪。
Collection是集合類(lèi)的根接口劣纲,Java中沒(méi)有提供這個(gè)接口的直接的實(shí)現(xiàn)類(lèi)。但是卻讓其被繼承產(chǎn)生了兩個(gè)接口List和Set谁鳍。List是一個(gè)有序癞季、可重復(fù)的集合劫瞳,提供了按索引訪問(wèn)的方式。Set中不能包含重復(fù)的元素绷柒。
Map是Java.util包中的另一個(gè)接口志于,它和Collection接口沒(méi)有關(guān)系,是相互獨(dú)立的废睦,但是都屬于集合類(lèi)的一部分伺绽。Map包含了key-value對(duì)。Map不能包含重復(fù)的key嗜湃,但是可以包含相同的value奈应。
Iterator,所有的集合類(lèi)都實(shí)現(xiàn)了Iterator接口购披,這是一個(gè)用于遍歷集合中元素的接口杖挣,主要包含以下三種方法:
- hasNext()是否還有下一個(gè)元素。
- next()返回下一個(gè)元素今瀑。
- remove()刪除當(dāng)前元素
3程梦、List点把、Set及Map的區(qū)別
1)List(有序橘荠、可重復(fù))
List里存放的對(duì)象是有序的,同時(shí)也是可以重復(fù)的郎逃,List關(guān)注的是索引哥童,擁有一系列和索引相關(guān)的方法,查詢速度快褒翰。因?yàn)橥鵯ist集合里插入或刪除數(shù)據(jù)時(shí)贮懈,會(huì)伴隨著后面數(shù)據(jù)的移動(dòng),所有插入刪除數(shù)據(jù)速度慢优训。
2)Set(無(wú)序朵你、不能重復(fù))
Set里存放的對(duì)象是無(wú)序,不能重復(fù)的揣非,集合中的對(duì)象不按特定的方式排序抡医,只是簡(jiǎn)單地把對(duì)象加入集合中。
3)Map(鍵值對(duì)早敬、鍵唯一忌傻、值不唯一)
Map集合中存儲(chǔ)的是鍵值對(duì),鍵不能重復(fù)搞监,值可以重復(fù)水孩。根據(jù)鍵得到值,對(duì)map集合遍歷時(shí)先得到鍵的set集合琐驴,對(duì)set集合進(jìn)行遍歷俘种,得到相應(yīng)的值秤标。
4、ArrayList和Array有什么區(qū)別?
1)Array可以容納基本類(lèi)型和對(duì)象安疗,而ArrayList只能容納引用類(lèi)型對(duì)象抛杨;
2)Array是指定大小的,而ArrayList大小是固定的荐类;
5怖现、ArrayList和LinkedList的區(qū)別?
ArrrayList底層的數(shù)據(jù)結(jié)構(gòu)是數(shù)組,支持隨機(jī)訪問(wèn)玉罐,而 LinkedList 的底層數(shù)據(jù)結(jié)構(gòu)是雙向循環(huán)鏈表屈嗤,不支持隨機(jī)訪問(wèn)。使用下標(biāo)訪問(wèn)一個(gè)元素吊输,ArrayList 的時(shí)間復(fù)雜度是 O(1)饶号,而 LinkedList 是 O(n)。ArrrayList查詢快季蚂,增刪改慢茫船,而LinkedList增刪快,卻查詢慢扭屁。
6算谈、ArrayList和Vector的區(qū)別?
ArrayList和Vector都實(shí)現(xiàn)了List接口,他們都是有序集合料滥,并且存放的元素是允許重復(fù)的然眼。它們的底層都是通過(guò)數(shù)組來(lái)實(shí)現(xiàn)的,因此列表這種數(shù)據(jù)結(jié)構(gòu)檢索數(shù)據(jù)速度快葵腹,但增刪改速度慢高每。
ArrayList和Vector的區(qū)別:
1)線程安全。Vector是線程安全的践宴,而ArrayList是線程不安全的鲸匿。因此在如果集合數(shù)據(jù)只有單線程訪問(wèn),那么使用ArrayList可以提高效率阻肩。而如果有多線程訪問(wèn)你的集合數(shù)據(jù)带欢,那么就必須要用Vector,因?yàn)橐WC數(shù)據(jù)安全磺浙。
2)數(shù)據(jù)增長(zhǎng)洪囤。ArrayList和Vector都有一個(gè)初始的容量大小,當(dāng)存儲(chǔ)進(jìn)它們里面的元素超過(guò)了容量時(shí)撕氧,就需要增加它們的存儲(chǔ)容量瘤缩。ArrayList每次增長(zhǎng)原來(lái)的0.5倍,而Vector增長(zhǎng)原來(lái)的一倍伦泥。ArrayList和Vector都可以設(shè)置初始空間的大小剥啤,Vector還可以設(shè)置增長(zhǎng)的空間大小锦溪,而ArrayList沒(méi)有提供設(shè)置增長(zhǎng)空間的方法。
7府怯、HashMap和Hashtable的區(qū)別
HashMap和Hashtable都實(shí)現(xiàn)了Map接口刻诊,并且都是key-value的數(shù)據(jù)結(jié)構(gòu)。它們的不同點(diǎn)主要在三個(gè)方面:
1)Hashtable是Java1.1的一個(gè)類(lèi)牺丙,它基于陳舊的Dictionary類(lèi)则涯。而HashMap是Java1.2引進(jìn)的Map接口的一個(gè)實(shí)現(xiàn)。
2)Hashtable是線程安全的冲簿,也就是說(shuō)是線程同步的粟判,而HashMap是線程不安全的。也就是說(shuō)在單線程環(huán)境下應(yīng)該用HashMap峦剔,這樣效率更高档礁。
3)HashMap允許將null值作為key或value,但Hashtable不允許(會(huì)拋出NullPointerException)吝沫。
8呻澜、LinkedHashMap及TreeMap
LinkedHashMap保存了記錄的插入順序,在用Iteraor遍歷LinkedHashMap時(shí)惨险,先得到的記錄肯定是先插入的羹幸,在遍歷的時(shí)候會(huì)比HashMap慢,有HashMap的全部特性平道。
TreeMap實(shí)現(xiàn)SortMap接口睹欲,能夠把它保存的記錄根據(jù)鍵排序供炼,默認(rèn)是按鍵值的升序排序(自然順序)一屋,也可以指定排序的比較器,當(dāng)用Iterator遍歷TreeMap時(shí)袋哼,得到的記錄是排過(guò)序的冀墨。不允許key值為空,非同步的涛贯;
七诽嘉、異常及異常處理相關(guān)
異常是發(fā)生在程序執(zhí)行過(guò)程中阻礙程序正常執(zhí)行的錯(cuò)誤事件。比如:用戶輸入錯(cuò)誤數(shù)據(jù)弟翘、硬件故障虫腋、網(wǎng)絡(luò)阻塞等都會(huì)導(dǎo)致出現(xiàn)異常。
1稀余、error和exception有什么區(qū)別
error表示系統(tǒng)級(jí)錯(cuò)誤悦冀,是java運(yùn)行環(huán)境內(nèi)部錯(cuò)誤或者硬件問(wèn)題,不能指望程序來(lái)處理這樣的問(wèn)題睛琳,除退出運(yùn)行外別無(wú)選擇盒蟆,它是Java虛擬機(jī)拋出的踏烙。
exception 表示程序需要捕捉、需要處理的異常历等,是由與程序設(shè)計(jì)的不完善而出現(xiàn)的問(wèn)題讨惩,程序必須處理的問(wèn)題。
2寒屯、運(yùn)行時(shí)異常和一般異常有何不同
Java提供了兩類(lèi)主要的異常:runtimeException和checkedException
一般異常(checkedException)主要是指IO異常荐捻、SQL異常等。對(duì)于這種異常寡夹,JVM要求我們必須對(duì)其進(jìn)行處理靴患。
運(yùn)行時(shí)異常(runtimeException)一般不處理,當(dāng)出現(xiàn)這類(lèi)異常時(shí)程序會(huì)由虛擬機(jī)接管要出。比如NullPointerException鸳君,而且這個(gè)異常也是最常見(jiàn)的異常之一。
出現(xiàn)運(yùn)行時(shí)異常的時(shí)候患蹂,程序會(huì)將異常一直向上拋或颊,一直拋到遇到處理代碼,如果沒(méi)有catch塊進(jìn)行處理传于,到了最上層囱挑,如果是多線程就有Thread.run()拋出,如果不是多線程那么就由main.run()拋出沼溜。拋出之后平挑,如果是線程,那么該線程也就終止了系草,如果是主程序通熄,那么該程序也就終止了。
3找都、throw和throws的區(qū)別
throw用于主動(dòng)拋出java.lang.Throwable 類(lèi)的一個(gè)實(shí)例化對(duì)象唇辨,意思是說(shuō)你可以通過(guò)關(guān)鍵字 throw 拋出一個(gè) Error 或者 一個(gè)Exception,如:throw new IllegalArgumentException(“size must be multiple of 2″)能耻。
而throws 的作用是作為方法聲明和簽名的一部分赏枚,方法被拋出相應(yīng)的異常以便調(diào)用者能處理。在Java 中晓猛,任何未處理的受檢查異常強(qiáng)制在 throws 子句中聲明饿幅。
4、你平時(shí)在項(xiàng)目中是怎樣對(duì)異常進(jìn)行處理的戒职。
1)盡量避免出現(xiàn)runtimeException 栗恩。例如對(duì)于可能出現(xiàn)空指針的代碼,帶使用對(duì)象之前一定要判斷一下該對(duì)象是否為空帕涌,必要的時(shí)候?qū)untimeException也進(jìn)行try catch處理摄凡。
2)進(jìn)行try catch處理的時(shí)候要在catch代碼塊中對(duì)異常信息進(jìn)行記錄续徽,通過(guò)調(diào)用異常類(lèi)的相關(guān)方法獲取到異常的相關(guān)信息,返回到web端亲澡,不僅要給用戶良好的用戶體驗(yàn)钦扭,也要能幫助程序員良好的定位異常出現(xiàn)的位置及原因。
3)使用自定義異常床绪,在業(yè)務(wù)代碼中將可預(yù)測(cè)的異常使用自定義異常拋出客情,最后通過(guò)AOP在最外層統(tǒng)一捕獲,并根據(jù)異常類(lèi)型封裝返回癞己。
八膀斋、Spring框架
Spring 是個(gè)java企業(yè)級(jí)應(yīng)用的開(kāi)源輕量級(jí)開(kāi)發(fā)框架。Spring主要用來(lái)開(kāi)發(fā)Java應(yīng)用痹雅,但是有些擴(kuò)展是針對(duì)構(gòu)建J2EE平臺(tái)的web應(yīng)用仰担。Spring 框架目標(biāo)是簡(jiǎn)化Java企業(yè)級(jí)應(yīng)用開(kāi)發(fā),并通過(guò)POJO為基礎(chǔ)的編程模型促進(jìn)良好的編程習(xí)慣绩社。
1摔蓝、Spring框架的主要功能及好處?
控制反轉(zhuǎn):Spring通過(guò)控制反轉(zhuǎn)實(shí)現(xiàn)了松散耦合愉耙,對(duì)象們給出它們的依賴(lài)贮尉,而不是創(chuàng)建或查找依賴(lài)的對(duì)象們。
面向切面的編程(AOP):Spring支持面向切面的編程朴沿,并且把應(yīng)用業(yè)務(wù)邏輯和系統(tǒng)服務(wù)分開(kāi)猜谚。
容器:Spring 包含并管理應(yīng)用中對(duì)象的生命周期和配置。
MVC框架:Spring的WEB框架是個(gè)精心設(shè)計(jì)的框架赌渣,是Web框架的一個(gè)很好的替代品魏铅。
事務(wù)管理:Spring 提供一個(gè)持續(xù)的事務(wù)管理接口,可以擴(kuò)展到上至本地事務(wù)下至全局事務(wù)(JTA)锡垄。
異常處理:Spring 提供方便的API把具體技術(shù)相關(guān)的異常(比如由JDBC沦零,Hibernate or JDO拋出的)轉(zhuǎn)化為一致的unchecked 異常祭隔。
2货岭、談?wù)勀銓?duì)Spring IOC和AOP的理解
IOC即控制反轉(zhuǎn)。就是對(duì)象的創(chuàng)建權(quán)反轉(zhuǎn)交給Spring疾渴,由容器控制程序之間的依賴(lài)關(guān)系千贯,作用是實(shí)現(xiàn)了程序的解耦合,而非傳統(tǒng)實(shí)現(xiàn)中搞坝,由程序代碼直接操控搔谴。最直觀的表達(dá)就是,IOC讓對(duì)象的創(chuàng)建不用去new了桩撮,可以由spring自動(dòng)生產(chǎn)敦第,這里用的就是java的反射機(jī)制峰弹,通過(guò)反射在運(yùn)行時(shí)動(dòng)態(tài)的去創(chuàng)建、調(diào)用對(duì)象芜果。spring就是根據(jù)配置文件在運(yùn)行時(shí)動(dòng)態(tài)的去創(chuàng)建對(duì)象鞠呈,并調(diào)用對(duì)象的方法的。
Spring的IOC有三種注入方式 :
根據(jù)屬性注入右钾,也叫set方法注入蚁吝;
根據(jù)構(gòu)造方法進(jìn)行注入;
根據(jù)注解進(jìn)行注入(Autowired和Resource)舀射。
AOP即面向切面編程窘茁,作為面向?qū)ο蟮囊环N補(bǔ)充,用于解剖封裝好的對(duì)象內(nèi)部脆烟,找出其中對(duì)多個(gè)對(duì)象產(chǎn)生影響的公共行為山林,并將其封裝為一個(gè)可重用的模塊,這個(gè)模塊被命名為“切面”(Aspect)邢羔,切面將那些與業(yè)務(wù)無(wú)關(guān)捌朴,卻被業(yè)務(wù)模塊共同調(diào)用的邏輯提取并封裝起來(lái),減少了系統(tǒng)中的重復(fù)代碼张抄,降低了模塊間的耦合度砂蔽,同時(shí)提高了系統(tǒng)的可維護(hù)性∈鸸撸可用于權(quán)限認(rèn)證左驾、日志、事務(wù)處理极谊。
AOP實(shí)現(xiàn)的關(guān)鍵在于AOP框架自動(dòng)創(chuàng)建的AOP代理诡右,AOP代理主要分為靜態(tài)代理和動(dòng)態(tài)代理。靜態(tài)代理的代表為AspectJ轻猖;動(dòng)態(tài)代理則以Spring AOP為代表帆吻。
1)AspectJ是靜態(tài)代理的增強(qiáng),所謂靜態(tài)代理咙边,就是AOP框架會(huì)在編譯階段生成AOP代理類(lèi)猜煮,因此也稱(chēng)為編譯時(shí)增強(qiáng),他會(huì)在編譯階段將AspectJ織入到Java字節(jié)碼中败许,運(yùn)行的時(shí)候就是增強(qiáng)之后的AOP對(duì)象王带。
2)Spring AOP使用的動(dòng)態(tài)代理,所謂的動(dòng)態(tài)代理就是說(shuō)AOP框架不會(huì)去修改字節(jié)碼市殷,而是每次運(yùn)行時(shí)在內(nèi)存中臨時(shí)為方法生成一個(gè)AOP對(duì)象愕撰,這個(gè)AOP對(duì)象包含了目標(biāo)對(duì)象的全部方法,并且在特定的切點(diǎn)做了增強(qiáng)處理,并回調(diào)原對(duì)象的方法搞挣。
Spring AOP中的動(dòng)態(tài)代理主要有兩種方式带迟,JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理:
JDK動(dòng)態(tài)代理通過(guò)反射來(lái)接收被代理的類(lèi),并且要求被代理的類(lèi)必須實(shí)現(xiàn)一個(gè)接口囱桨。JDK動(dòng)態(tài)代理的核心是InvocationHandler接口和Proxy類(lèi)邮旷。生成的代理對(duì)象的方法調(diào)用都會(huì)委托到InvocationHandler.invoke()方法,當(dāng)我們調(diào)用代理類(lèi)對(duì)象的方法時(shí)蝇摸,這個(gè)“調(diào)用”會(huì)轉(zhuǎn)送到invoke方法中婶肩,代理類(lèi)對(duì)象作為proxy參數(shù)傳入,參數(shù)method標(biāo)識(shí)了我們具體調(diào)用的是代理類(lèi)的哪個(gè)方法貌夕,args為這個(gè)方法的參數(shù)律歼。
如果目標(biāo)類(lèi)沒(méi)有實(shí)現(xiàn)接口,那么Spring AOP會(huì)選擇使用CGLIB來(lái)動(dòng)態(tài)代理目標(biāo)類(lèi)啡专。CGLIB(Code Generation Library)险毁,是一個(gè)代碼生成的類(lèi)庫(kù),可以在運(yùn)行時(shí)動(dòng)態(tài)的生成指定類(lèi)的一個(gè)子類(lèi)對(duì)象们童,并覆蓋其中特定方法畔况,覆蓋方法時(shí)可以添加增強(qiáng)代碼,從而實(shí)現(xiàn)AOP慧库。CGLIB是通過(guò)繼承的方式做的動(dòng)態(tài)代理跷跪,因此如果某個(gè)類(lèi)被標(biāo)記為final,那么它是無(wú)法使用CGLIB做動(dòng)態(tài)代理的齐板。
3)靜態(tài)代理與動(dòng)態(tài)代理區(qū)別在于生成AOP代理對(duì)象的時(shí)機(jī)不同吵瞻,相對(duì)來(lái)說(shuō)AspectJ的靜態(tài)代理方式具有更好的性能,但是AspectJ需要特定的編譯器進(jìn)行處理甘磨,而Spring AOP則無(wú)需特定的編譯器處理橡羞。
IOC讓相互協(xié)作的組件保持松散的耦合,而AOP編程允許你把遍布于應(yīng)用各層的功能分離出來(lái)形成可重用的功能組件济舆。
3卿泽、SpringMVC的原理及執(zhí)行流程?
SpringMVC核心是前端控制器DispatcherServlet滋觉,一個(gè)請(qǐng)求的執(zhí)行流程:
1)用戶發(fā)送請(qǐng)求到前端控制器DispatcherServlet签夭;
2)DispatcherServlet收到請(qǐng)求后,調(diào)用HandlerMapping處理器映射器椎瘟,請(qǐng)求獲取Handle處理器覆致;
3)處理器映射器根據(jù)請(qǐng)求url找到具體的處理器,生成處理器對(duì)象及處理器攔截器(如果有則生成)一并返回給DispatcherServlet肺蔚;
4)DispatcherServlet通過(guò)HandlerAdapter處理器適配器調(diào)用處理器;
5)處理器處理業(yè)務(wù)儡羔,完成后返回ModelAndView宣羊;
- HandlerAdapter將Handler執(zhí)行結(jié)果ModelAndView返回給DispatcherServlet璧诵;
7)DispatcherServlet再將ModelAndView傳給ViewResolver視圖解析器進(jìn)行解析;
8)ViewResolver解析后返回具體View仇冯;
9)DispatcherServlet對(duì)View進(jìn)行渲染視圖(即將模型數(shù)據(jù)填充至視圖中)之宿,并響應(yīng)給用戶。
九苛坚、數(shù)據(jù)庫(kù)
數(shù)據(jù)庫(kù)也是Java開(kāi)發(fā)者的面試中的重點(diǎn)比被,這里只說(shuō)說(shuō)常見(jiàn)的數(shù)據(jù)庫(kù)面試題。
1泼舱、數(shù)據(jù)庫(kù)三范式等缀?
第一范式(1NF):數(shù)據(jù)庫(kù)表中的字段都是單一屬性的,不可再分娇昙。這個(gè)單一屬性由基本類(lèi)型構(gòu)成尺迂,包括整型、實(shí)數(shù)冒掌、字符型噪裕、邏輯型、日期型等股毫。
第二范式(2NF):數(shù)據(jù)庫(kù)表中不存在非關(guān)鍵字段對(duì)任一候選關(guān)鍵字段的部分函數(shù)依賴(lài)(部分函數(shù)依賴(lài)指的是存在組合關(guān)鍵字中的某些字段決定非關(guān)鍵字段的情況)膳音,也即所有非關(guān)鍵字段都完全依賴(lài)于任意一組候選關(guān)鍵字。
第三范式(3NF):在第二范式的基礎(chǔ)上铃诬,數(shù)據(jù)表中如果不存在非關(guān)鍵字段對(duì)任一候選關(guān)鍵字段的傳遞函數(shù)依賴(lài)則符合第三范式严蓖。所謂傳遞函數(shù)依賴(lài),指的是如果存在”A → B → C”的決定關(guān)系氧急,則C傳遞函數(shù)依賴(lài)于A颗胡。
2、數(shù)據(jù)庫(kù)事務(wù)的四大特性吩坝?
1) 原子性(Atomicity)
事務(wù)被視為不可分割的最小單元毒姨,事務(wù)的所有操作要么全部提交成功,要么全部失敗回滾钉寝』∧牛回滾可以用日志來(lái)實(shí)現(xiàn),日志記錄著事務(wù)所執(zhí)行的修改操作嵌纲,在回滾時(shí)反向執(zhí)行這些修改操作即可俘枫。
2)一致性(Consistency)
數(shù)據(jù)庫(kù)在事務(wù)執(zhí)行前后都保持一致性狀態(tài)。在一致性狀態(tài)下逮走,所有事務(wù)對(duì)一個(gè)數(shù)據(jù)的讀取結(jié)果都是相同的鸠蚪。
3)隔離性(Isolation)
一個(gè)事務(wù)所做的修改在最終提交以前,對(duì)其它事務(wù)是不可見(jiàn)的。
4)持久性(Durability)
一旦事務(wù)提交茅信,則其所做的修改將會(huì)永遠(yuǎn)保存到數(shù)據(jù)庫(kù)中盾舌。即使系統(tǒng)發(fā)生崩潰,事務(wù)執(zhí)行的結(jié)果也不能丟失蘸鲸⊙矗可以通過(guò)數(shù)據(jù)庫(kù)備份和恢復(fù)來(lái)實(shí)現(xiàn),在系統(tǒng)發(fā)生崩潰時(shí)酌摇,使用備份的數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)恢復(fù)膝舅。
3、索引是什么窑多?有什么作用以及優(yōu)缺點(diǎn)仍稀?
1)什么是索引【Index】
是一種快速查詢表中內(nèi)容的機(jī)制,類(lèi)似于新華字典的目錄怯伊;運(yùn)用在表中某個(gè)些字段上琳轿,但存儲(chǔ)時(shí),獨(dú)立于表之外耿芹;
2)什么時(shí)候【要】創(chuàng)建索引
(1)表經(jīng)常進(jìn)行 SELECT 操作
(2)表很大(記錄超多)崭篡,記錄內(nèi)容分布范圍很廣
(3)列名經(jīng)常在 WHERE 子句或連接條件中出現(xiàn)
3)什么時(shí)候【不要】創(chuàng)建索引
(1)表經(jīng)常進(jìn)行 INSERT/UPDATE/DELETE 操作
(2)表很小(記錄超少)
(3)列名不經(jīng)常作為連接條件或出現(xiàn)在 WHERE 子句中
4)索引優(yōu)缺點(diǎn):
(1)索引加快數(shù)據(jù)庫(kù)的檢索速度
(2)索引降低了插入、刪除吧秕、修改等維護(hù)任務(wù)的速度(雖然索引可以提高查詢速度琉闪,但是它們也會(huì)導(dǎo)致數(shù)據(jù)庫(kù)系統(tǒng)更新數(shù)據(jù)的性能下降,因?yàn)榇蟛糠謹(jǐn)?shù)據(jù)更新需要同時(shí)更新索引)
(3)唯一索引可以確保每一行數(shù)據(jù)的唯一性砸彬,通過(guò)使用索引颠毙,可以在查詢的過(guò)程中使用優(yōu)化隱藏器,提高系統(tǒng)的性能
(4)索引需要占物理和數(shù)據(jù)空間
關(guān)于數(shù)據(jù)庫(kù)表設(shè)計(jì)等砂碉,今天就不多說(shuō)了蛀蜜,畢竟這需要一定的積累,不會(huì)一時(shí)不會(huì)就能說(shuō)完的增蹭,如果你想了解和學(xué)習(xí)滴某,可以關(guān)注公眾號(hào)【禿頭哥編程】。