1缀雳、面向?qū)ο蟮奶卣饔心男┓矫?
答:面向?qū)ο蟮奶卣髦饕幸韵聨讉€(gè)方面:
-- 抽象:抽象是將一類對象的共同特征總結(jié)出來構(gòu)造類的過程,包括數(shù)據(jù)抽象和行為抽象兩方面嫂便。抽象只關(guān)注對象有哪些屬性和行為念赶,并不關(guān)具體細(xì)節(jié)是什么。
-- 封裝:通常認(rèn)為封裝是把數(shù)據(jù)和操作數(shù)據(jù)的方法綁定起來怖竭,對數(shù)據(jù)的訪問只能通過已定義的接口锥债。面向?qū)ο蟮谋举|(zhì)就是將現(xiàn)實(shí)世界描繪成一系列完全自治、封閉的對象。我們在類中編寫的方法就是對實(shí)現(xiàn)細(xì)節(jié)的一種封裝;我們編寫一個(gè)類就是對數(shù)據(jù)和數(shù)據(jù)操作的封裝哮肚∫阏可以說,封裝就是隱藏一切可隱藏的東西绽左,只向外界提供最簡單的編程接口(可以想想普通洗衣機(jī)和全自動洗衣機(jī)的差別悼嫉,明顯全自動洗衣機(jī)封裝更好因此操作起來更簡單;我們現(xiàn)在使用的智能手機(jī)也是封裝得足夠好的,因?yàn)閹讉€(gè)按鍵就搞定了所有的事情)拼窥。
-- 繼承:繼承是從已有類得到繼承信息創(chuàng)建新類的過程戏蔑。提供繼承信息的類被稱為父類(超類、基類);得到繼承信息的類被稱為子類(派生類)鲁纠。繼承讓變化中的軟件系統(tǒng)有了一定的延續(xù)性总棵,同時(shí)繼承也是封裝程序中可變因素的重要手段。
-- 多態(tài)性:多態(tài)性是指允許不同子類型的對象對同一消息作出不同的響應(yīng)改含。簡單的說就是用同樣的對象引用調(diào)用同樣的方法但是做了不同的事情情龄。多態(tài)性分為編譯時(shí)的多態(tài)性和運(yùn)行時(shí)的多態(tài)性。方法重載(overload)實(shí)現(xiàn)的是編譯時(shí)的多態(tài)性(也稱為前綁定)捍壤,而方法重寫(override)實(shí)現(xiàn)的是運(yùn)行時(shí)的多態(tài)性(也稱為后綁定)骤视。
2、訪問修飾符public,private,protected,以及不寫(默認(rèn))時(shí)的區(qū)別?
答:類的成員不寫訪問修飾時(shí)默認(rèn)為default鹃觉。范圍見下圖:
修飾符 | 當(dāng)前類 | 同 包 | 子 類 | 其他包 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
3专酗、String 是最基本的數(shù)據(jù)類型嗎?
答:不是。Java中的基本數(shù)據(jù)類型只有8個(gè):byte盗扇、short祷肯、int、long疗隶、float佑笋、double、char斑鼻、boolean蒋纬。
4、int和Integer有什么區(qū)別?
答:Java是一個(gè)近乎純潔的面向?qū)ο缶幊陶Z言卵沉,但是為了編程的方便還是引入了基本數(shù)據(jù)類型颠锉,但是為了能夠?qū)⑦@些基本數(shù)據(jù)類型當(dāng)成對象操作,Java為每一個(gè)基本數(shù)據(jù)類型都引入了對應(yīng)的包裝類型(wrapper class)史汗,int的包裝類就是Integer琼掠,從Java 5開始引入了自動裝箱/拆箱機(jī)制,使得二者可以相互轉(zhuǎn)換停撞。
Java 為每個(gè)原始類型提供了包裝類型:
原始類型: boolean瓷蛙,char悼瓮,byte,short艰猬,int横堡,long,float冠桃,double
包裝類型:Boolean命贴,Character,Byte食听,Short胸蛛,Integer,Long樱报,F(xiàn)loat葬项,Double
5、重載(Overload)和重寫(Override)的區(qū)別迹蛤?
答:方法的重載和重寫都是實(shí)現(xiàn)多態(tài)的方式民珍,區(qū)別在于前者實(shí)現(xiàn)的是編譯時(shí)的多態(tài)性,而后者實(shí)現(xiàn)的是運(yùn)行時(shí)的多態(tài)性盗飒。重載發(fā)生在一個(gè)類中嚷量,同名的方法如果有不同的參數(shù)列表(參數(shù)類型不同、參數(shù)個(gè)數(shù)不同或者二者都不同)則視為重載;重寫發(fā)生在子類與父類之間箩兽,重寫要求子類重寫方法與父類被重寫方法有相同的返回類型津肛,比父類被重寫方法更好訪問(只能比父類訪問范圍更大)章喉,不能比父類被重寫方法聲明更多的異常(里氏代換原則)汗贫。
6、抽象類(abstract class)和接口(interface)有什么異同?
答:抽象類和接口都不能夠?qū)嵗╪ew XXX)秸脱,但可以定義抽象類和接口類型的引用(XXX xx = new XXX的實(shí)現(xiàn)類)落包。一個(gè)類如果繼承了某個(gè)抽象類或者實(shí)現(xiàn)了某個(gè)接口都需要對其中的抽象方法全部進(jìn)行實(shí)現(xiàn),否則該類仍然需要被聲明為抽象類摊唇。接口比抽象類更加抽象咐蝇,因?yàn)槌橄箢愔锌梢远x構(gòu)造器,可以有抽象方法和具體方法巷查,而接口中不能定義構(gòu)造器而且其中的方法全部都是抽象方法有序。抽象類中的成員可以是private、default岛请、protected旭寿、public的,而接口中的成員全都是public的崇败。抽象類中可以定義成員變量盅称,而接口中定義的成員變量實(shí)際上都是常量肩祥。有抽象方法的類必須被聲明為抽象類,而抽象類未必要有抽象方法缩膝。
7混狠、Java里的傳引用和傳值的區(qū)別是什么?
答:傳引用是指傳遞的是地址而不是值本身疾层,傳值則是傳遞值的一份拷貝将饺。
8、==與equals的區(qū)別痛黎?
答:==比較的是引用而equals方法比較的是內(nèi)容俯逾。public boolean equals(Object obj) 這個(gè)方法是由Object對象提供的,可以由子類進(jìn)行重寫舅逸。
9桌肴、如何將String類型轉(zhuǎn)化成Number類型?
答:Integer類的valueOf方法可以將String轉(zhuǎn)成Number琉历。
10坠七、&操作符和&&操作符有什么區(qū)別?
答:&是位運(yùn)算符,表示按位與運(yùn)算旗笔;&&是邏輯運(yùn)算符彪置,表示邏輯與(and)。除了長得像沒有半點(diǎn)關(guān)系蝇恶。
11拳魁、switch 語句能否作用在byte 上,能否作用在long 上撮弧,能否作用在String上?
答:在switch(expr1)中潘懊,expr1只能是一個(gè)整數(shù)表達(dá)式或者枚舉常量(更大字體),整數(shù)表達(dá)式可以是int基本類型或Integer包裝類型贿衍,由于授舟,byte,short,char都可以隱含轉(zhuǎn)換為int,所以贸辈,這些類型以及這些類型的包裝類型也是可以的释树。顯然,long和String類型都不符合switch的語法規(guī)定擎淤,并且不能被隱式轉(zhuǎn)換成int類型奢啥,所以,它們不能作用于swtich語句中嘴拢。
12桩盲、short s1 = 1; s1 = s1 + 1; 有什么錯(cuò)? short s1 = 1; s1 +=1; 有什么錯(cuò)?
答:對于
short s1 = 1;
s1 = s1 + 1;
由于s1+1運(yùn)算時(shí)會自動提升表達(dá)式的類型,所以結(jié)果是int型炊汤,再賦值給short類型s1時(shí)正驻,編譯器將報(bào)告需要強(qiáng)制轉(zhuǎn)換類型的錯(cuò)誤弊攘。
對于
short s1 = 1;
s1 += 1;
由于 +=是java語言規(guī)定的運(yùn)算符,java編譯器會對它進(jìn)行特殊處理姑曙,因此可以正確編譯襟交。
13、使用final 關(guān)鍵字修飾一個(gè)變量時(shí)伤靠,是引用不能變捣域,還是引用的對象不能變?
答:使用final關(guān)鍵字修飾一個(gè)變量時(shí)宴合,是指引用變量不能變焕梅,引用變量所指向的對象中的內(nèi)容還是可以改變的。例如卦洽,對于如下語句:
final StringBuffer a=new StringBuffer("abcdefg");
執(zhí)行如下語句將報(bào)告編譯期錯(cuò)誤:
a=new StringBuffer("");
但是贞言,執(zhí)行如下語句則可以通過編譯:
a.append("xxoo");
14、String s = new String("xyz"); 創(chuàng)建了幾個(gè)String Object?
答:兩個(gè)或一個(gè)阀蒂,”xyz”對應(yīng)一個(gè)對象该窗,這個(gè)對象放在字符串常量緩沖區(qū),常量”xyz”不管出現(xiàn)多少遍蚤霞,都是緩沖區(qū)中的那一個(gè)酗失。New String每寫一遍,就創(chuàng)建一個(gè)新的對象昧绣,它一句那個(gè)常量”xyz”對象的內(nèi)容來創(chuàng)建出一個(gè)新String對象规肴。如果以前就用過’xyz’,這句代表就不會創(chuàng)建”xyz”自己了夜畴,直接從緩沖區(qū)拿拖刃。
15、StringBuffer 與StringBuilder的區(qū)別斩启?
答:StringBuilder不是線程安全的序调,運(yùn)行效率高;StringBuffer是線程安全的兔簇,運(yùn)行效率不及StringBuilder。
16硬耍、數(shù)組有沒有l(wèi)ength() 這個(gè)方法?String 有沒有l(wèi)ength() 這個(gè)方法垄琐?
答:數(shù)組沒有l(wèi)ength()這個(gè)方法,有l(wèi)ength的屬性经柴。String有有l(wèi)ength()這個(gè)方法狸窘。
17、final, finally, finalize的區(qū)別坯认?
答:final用于聲明屬性翻擒,方法和類氓涣,分別表示屬性不可變,方法不可覆蓋陋气,類不可繼承劳吠。
finally是異常處理語句結(jié)構(gòu)的一部分,表示總是執(zhí)行巩趁。
finalize是Object類的一個(gè)方法痒玩,在垃圾收集器執(zhí)行的時(shí)候會調(diào)用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時(shí)的其他資源回收议慰。
18蠢古、啟動一個(gè)線程是用run() 還是start()?
答:啟動一個(gè)線程是調(diào)用start()方法,使線程就緒狀態(tài)别凹,以后可以被調(diào)度為運(yùn)行狀態(tài)草讶,一個(gè)線程必須關(guān)聯(lián)一些具體的執(zhí)行代碼,run()方法是該線程所關(guān)聯(lián)執(zhí)行的代碼炉菲。
19到涂、字節(jié)流與字符流的區(qū)別?
答:在應(yīng)用中颁督,經(jīng)常要完全是字符的一段文本輸出去或讀進(jìn)來践啄,用字節(jié)流可以嗎?計(jì)算機(jī)中的一切最終都是二進(jìn)制的字節(jié)形式存在沉御。對于“中國”這些字符屿讽,首先要得到其對應(yīng)的字節(jié),然后將字節(jié)寫入到輸出流吠裆。讀取時(shí)伐谈,首先讀到的是字節(jié),可是我們要把它顯示為字符试疙,我們需要將字節(jié)轉(zhuǎn)換成字符诵棵。由于這樣的需求很廣泛,人家專門提供了字符流的包裝類祝旷。底層設(shè)備永遠(yuǎn)只接受字節(jié)數(shù)據(jù)履澳,有時(shí)候要寫字符串到底層設(shè)備,需要將字符串轉(zhuǎn)成字節(jié)再進(jìn)行寫入怀跛。字符流是字節(jié)流的包裝距贷,字符流則是直接接受字符串,它內(nèi)部將串轉(zhuǎn)成字節(jié)吻谋,再寫入底層設(shè)備忠蝗,這為我們向IO設(shè)別寫入或讀取字符串提供了一點(diǎn)點(diǎn)方便。字符向字節(jié)轉(zhuǎn)換時(shí)漓拾,要注意編碼的問題阁最,因?yàn)樽址D(zhuǎn)成字節(jié)數(shù)組戒祠,其實(shí)是轉(zhuǎn)成該字符的某種編碼的字節(jié)形式,讀取也是反之的道理速种。
20姜盈、什么是java 序列化,如何實(shí)現(xiàn)java 序列化哟旗?
答:我們有時(shí)候?qū)⒁粋€(gè)java對象變成字節(jié)流的形式傳出去或者從一個(gè)字節(jié)流中恢復(fù)成一個(gè)java對象贩据,例如,要將java對象存儲到硬盤或者傳送給網(wǎng)絡(luò)上的其他計(jì)算機(jī)闸餐,這個(gè)過程我們可以自己寫代碼去把一個(gè)java對象變成某個(gè)格式的字節(jié)流再傳輸饱亮,但是,jre本身就提供了這種支持舍沙,我們可以調(diào)用OutputStream的writeObject方法來做近上,如果要讓java幫我們做,要被傳輸?shù)膶ο蟊仨殞?shí)現(xiàn)serializable接口拂铡,這樣壹无,javac編譯時(shí)就會進(jìn)行特殊處理,編譯的類才可以被writeObject方法操作感帅,這就是所謂的序列化斗锭。需要被序列化的類必須實(shí)現(xiàn)Serializable接口。
21失球、Servlet的生命周期岖是?
答:servlet有良好的生存期的定義,包括加載和實(shí)例化实苞、初始化豺撑、處理請求以及服務(wù)結(jié)束。這個(gè)生存期由javax.servlet.Servlet接口的init,service和destroy方法表達(dá)黔牵。web容器加載servlet聪轿,生命周期開始,通過調(diào)用servlet的init()方法進(jìn)行servlet的初始化猾浦,通過調(diào)用service()方法實(shí)現(xiàn)陆错,根據(jù)請求的不同調(diào)用不同的doXXX方法(doGet,doPost)等跃巡,結(jié)束服務(wù)危号,web容器調(diào)用servlet的destroy()方法。
22素邪、servlet api 中 forward()與redirect()的區(qū)別?
答:前者僅是容器中控制權(quán)的轉(zhuǎn)向猪半,在客戶端瀏覽器地址欄中不會顯示出轉(zhuǎn)向后的地址兔朦;后者則是完全的跳轉(zhuǎn)偷线,瀏覽器將會得到跳轉(zhuǎn)的地址,并重新發(fā)送請求鏈接沽甥。這樣声邦,從瀏覽器的地址欄中可以看到跳轉(zhuǎn)后的鏈接地址。所以摆舟,前者更加高效亥曹,在前者可以滿足需要時(shí),盡量使用forward()方法恨诱,并且媳瞪,這樣也有助于隱藏實(shí)際的鏈接。在有些情況下照宝,比如蛇受,需要跳轉(zhuǎn)到一個(gè)其它服務(wù)器上的資源,則必須使用sendRedirect()方法厕鹃。
23兢仰、 jsp 有哪些內(nèi)置對象? 作用分別是什么?
答:JSP共有以下9個(gè)內(nèi)置的對象:
-- request, 表示HttpServletRequest對象剂碴,它包含了有關(guān)瀏覽器請求的信息把将,并且提供了幾個(gè)用于獲取cookie, header, 和session數(shù)據(jù)的有用的方法。
-- response忆矛,表示HttpServletResponse對象察蹲,并提供了幾個(gè)用于設(shè)置送回瀏覽器的響應(yīng)的方法(如cookies,頭信息等)。
-- pageContext洪碳,表示一個(gè)javax.servlet.jsp.PageContext對象递览。它是用于方便存取各種范圍的名字空間、servlet相關(guān)的對象的API瞳腌,并且包裝了通用的servlet相關(guān)功能的方法绞铃。
-- session,表示一個(gè)請求的javax.servlet.http.HttpSession對象嫂侍。Session可以存貯用戶的狀態(tài)信息儿捧。
-- application,表示一個(gè)javax.servle.ServletContext對象挑宠。這有助于查找有關(guān)servlet引擎和servlet環(huán)境的信息菲盾。
-- out,out對象是javax.jsp.JspWriter的一個(gè)實(shí)例各淀,并提供了幾個(gè)方法使你能用于向?yàn)g覽器回送輸出結(jié)果伙单。
-- config,表示一個(gè)javax.servlet.ServletConfig對象秉溉。該對象用于存取servlet實(shí)例的初始化參數(shù)。
-- page璃俗,表示從該頁面產(chǎn)生的一個(gè)servlet實(shí)例。
-- exception 針對錯(cuò)誤網(wǎng)頁悉默,未捕捉的例外
24城豁、JSP中動態(tài)INCLUDE與靜態(tài)INCLUDE的區(qū)別?
答:動態(tài)INCLUDE用<jsp:include page=included.jsp flush=true/>實(shí)現(xiàn)它總是會檢查所含文件中的變化抄课,適合用于包含動態(tài)頁面唱星,并且可以帶參數(shù)。
靜態(tài)INCLUDE用<%@include file=included.htm %>實(shí)現(xiàn),不會檢查所含文件的變化跟磨,適用于包含靜態(tài)頁面间聊。
25、JSP 和Servlet 有哪些相同點(diǎn)和不同點(diǎn)吱晒,他們之間的聯(lián)系是什么甸饱?
答:JSP是Servlet技術(shù)的擴(kuò)展,本質(zhì)上還是Servlet仑濒。JSP側(cè)重于表現(xiàn)層叹话,Servlet主要用于控制邏輯。
26墩瞳、MVC 是什么驼壶?各個(gè)部分都有那些技術(shù)來實(shí)現(xiàn)?
答:MVC是Model-View-Controller的簡寫。
Model代表的是應(yīng)用的業(yè)務(wù)邏輯(通過JavaBean喉酌,EJB組件實(shí)現(xiàn))
View是應(yīng)用的表示面(由JSP頁面產(chǎn)生)
Controller是提供應(yīng)用的處理過程控制(一般是一個(gè)Servlet)
通過這種設(shè)計(jì)模型把應(yīng)用邏輯热凹,處理過程和顯示邏輯分成不同的組件實(shí)現(xiàn)。這些組件可以進(jìn)行交互和重用泪电。
27般妙、JDBC 中的PreparedStatement 相比Statement 的好處?
答:PreparedStatement 會緩存指令相速,所以性能比Statement高碟渺。PreparedStatement在預(yù)編譯的時(shí)候過濾了特殊字符串,所以會防止SQL注入突诬。
28苫拍、數(shù)據(jù)庫三范式是什么?
答:第一范式(1NF):數(shù)據(jù)庫表中的字段都是單一屬性的,不可再分旺隙。這個(gè)單一屬性由基本類型構(gòu)成绒极,包括整型、實(shí)數(shù)蔬捷、字符型垄提、邏輯型、日期型等。
第二范式(2NF):數(shù)據(jù)庫表中不存在非關(guān)鍵字段對任一候選關(guān)鍵字段的部分函數(shù)依賴(部分函數(shù)依賴指的是存在組合關(guān)鍵字中的某些字段決定非關(guān)鍵字段的情況)塔淤,也即所有非關(guān)鍵字段都完全依賴于任意一組候選關(guān)鍵字摘昌。
第三范式(3NF):在第二范式的基礎(chǔ)上速妖,數(shù)據(jù)表中如果不存在非關(guān)鍵字段對任一候選關(guān)鍵字段的傳遞函數(shù)依賴則符合第三范式高蜂。所謂傳遞函數(shù)依賴,指的是如果存在"A → B → C"的決定關(guān)系罕容,則C傳遞函數(shù)依賴于A备恤。因此,滿足第三范式的數(shù)據(jù)庫表應(yīng)該不存在如下依賴關(guān)系: 關(guān)鍵字段 → 非關(guān)鍵字段x → 非關(guān)鍵字段y
29锦秒、什么是主鍵?什么是外鍵?
答:主鍵是表里的(一個(gè)或多個(gè))字段露泊,只用來定義表格里的行;主鍵里的值總是唯一的。外鍵是一個(gè)用來建立兩個(gè)表格之間關(guān)系的約束旅择。這種關(guān)系一般都涉及一個(gè)表格里的主鍵字段與另外一個(gè)表(可能是同一表)里的字段惭笑。那么這些相連的字段就是外鍵。
30生真、什么是數(shù)據(jù)庫事務(wù)沉噩?事務(wù)有哪些特性?簡述事務(wù)的隔離級別柱蟀?
答:事務(wù)是是一系列的數(shù)據(jù)庫操作川蒙,是數(shù)據(jù)庫應(yīng)用的基本邏輯單位。
事務(wù)有原子性长已、一致性畜眨、隔離性、持久性术瓮。
-- 原子性康聂。即不可分割性,事務(wù)要么全部被執(zhí)行胞四,要么就全部不被執(zhí)行恬汁。
-- 隔離性。在事務(wù)正確提交之前撬讽,不允許把該事務(wù)對數(shù)據(jù)的任何改變提供給任何其他事務(wù)蕊连。
-- 持久性。事務(wù)正確提交后游昼,其結(jié)果將永久保存在數(shù)據(jù)庫中甘苍,即使在事務(wù)提交后有了其他故障,事務(wù)的處理結(jié)果也會得到保存烘豌。
事務(wù)的隔離級別:讀未提交(Read Uncommitted):可以發(fā)生臟讀载庭、不可重復(fù)讀和幻讀;讀提交(Read Committed):不可以發(fā)生臟讀可以發(fā)生不可重復(fù)讀和幻讀;可重復(fù)讀惹艟邸(Repeatable Read):不可以發(fā)生臟讀和不可重復(fù)讀靖榕,可以發(fā)生幻讀;序列化(Serializable):不可以發(fā)生臟讀顽铸、不可重復(fù)讀和幻讀茁计。
-- 臟讀:臟讀又稱無效數(shù)據(jù)的讀出,是指在數(shù)據(jù)庫訪問中谓松,事務(wù)T1將某一值修改星压,然后事務(wù)T2讀取該值,此后T1因?yàn)槟撤N原因撤銷對該值的修改鬼譬,這就導(dǎo)致了T2所讀取到的數(shù)據(jù)是無效的娜膘。
事務(wù)一 | 事務(wù)二 |
---|
/* Query 1 /
SELECT age FROM users WHERE id = 1;
/ will read 20 /
/ Query 2 /
UPDATE users SET age = 21 WHERE id = 1;
/ No commit here /
/ Query 1 /
SELECT age FROM users WHERE id = 1;
/ will read 21 */
ROLLBACK;
-- 不可重復(fù)讀:是指在數(shù)據(jù)庫訪問中,一個(gè)事務(wù)范圍內(nèi)兩個(gè)相同的查詢卻返回了不同數(shù)據(jù)优质。這是由于查詢時(shí)系統(tǒng)中其他事務(wù)修改的提交而引起的竣贪。比如事務(wù)T1讀取某一數(shù)據(jù),事務(wù)T2讀取并修改了該數(shù)據(jù)巩螃,T1為了對讀取值進(jìn)行檢驗(yàn)而再次讀取該數(shù)據(jù)演怎,便得到了不同的結(jié)果。
事務(wù)一 事務(wù)二
/* Query 1 */
SELECT * FROM users WHERE id = 1;
/* Query 2 /
UPDATE users SET age = 21 WHERE id = 1;
COMMIT;
/ Query 1 */
SELECT * FROM users WHERE id = 1;
COMMIT;
-- 幻讀:幻讀是指當(dāng)事務(wù)不是獨(dú)立執(zhí)行時(shí)發(fā)生的一種現(xiàn)象牺六,例如第一個(gè)事務(wù)對一個(gè)表中的數(shù)據(jù)進(jìn)行了修改颤枪,比如這種修改涉及到表中的“全部數(shù)據(jù)行”。同時(shí)淑际,第二個(gè)事務(wù)也修改這個(gè)表中的數(shù)據(jù)畏纲,這種修改是向表中插入“一行新數(shù)據(jù)”。那么春缕,以后就會發(fā)生操作第一個(gè)事務(wù)的用戶發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行盗胀,就好象發(fā)生了幻覺一樣。
事務(wù)一 事務(wù)二
/* Query 1 */
SELECT * FROM users;
/* Query 2 /
INSERT INTO users VALUES ( 3, 'Bob', 27 );
COMMIT;
/ Query 1 */
SELECT * FROM users;
31锄贼、HashMap的實(shí)現(xiàn)原理票灰?
答:在java編程語言中,最基本的結(jié)構(gòu)就是兩種宅荤,一個(gè)是數(shù)組屑迂,另外一個(gè)是模擬指針(引用),所有的數(shù)據(jù)結(jié)構(gòu)都可以用這兩個(gè)基本結(jié)構(gòu)來構(gòu)造的冯键,HashMap也不例外惹盼。HashMap實(shí)際上是一個(gè)“鏈表散列”的數(shù)據(jù)結(jié)構(gòu),即數(shù)組和鏈表的結(jié)合體惫确。
HashMap是基于hashing的原理手报,我們使用put(key, value)存儲對象到HashMap中蚯舱,使用get(key)從HashMap中獲取對象。當(dāng)我們給put()方法傳遞鍵和值時(shí)掩蛤,我們先對鍵調(diào)用hashCode()方法枉昏,返回的hashCode用于找到數(shù)組中的位置來儲存Entry對象。當(dāng)對象的hashcode相同時(shí)揍鸟,它們在數(shù)組中的位置相同兄裂,“碰撞”會發(fā)生。因?yàn)镠ashMap使用線性鏈表存儲對象蜈亩,這個(gè)Entry會存儲在線性鏈表中懦窘。將會調(diào)用key的eqauls()方法比較決定是采用覆蓋行為(返回 true),還是產(chǎn)生 Entry 鏈(返回 false)稚配,新加入的放在鏈頭,最先加入的放在鏈尾港华。
32道川、HashMap與HashTable的區(qū)別?
答:HashMap可以接受null鍵值和值立宜,而Hashtable則不能冒萄。
Hashtable是線程安全的,通過synchronized實(shí)現(xiàn)線程同步橙数。而HashMap是非線程安全的尊流,但是速度比Hashtable快。
33灯帮、ArrayList與LinkedList的區(qū)別崖技?
答:兩者都實(shí)現(xiàn)的是List接口,不同之處在于:
-- ArrayList是基于動態(tài)數(shù)組實(shí)現(xiàn)的钟哥,LinkedList是基于鏈表的數(shù)據(jù)結(jié)構(gòu)迎献。
-- get訪問List內(nèi)部任意元素時(shí),ArrayList的性能要比LinkedList性能好腻贰。LinkedList中的get方法是要按照順序從列表的一端開始檢查吁恍,直到另一端
-- 對于新增和刪除操作LinkedList要強(qiáng)于ArrayList,因?yàn)锳rrayList要移動數(shù)據(jù)
附加:
LinkedList實(shí)現(xiàn)了List接口播演,允許null元素冀瓦。此外LinkedList提供額外的get,remove写烤,insert方法在LinkedList的首部或尾部翼闽。這些操作使LinkedList可被用作堆棧(stack),隊(duì)列(queue)或雙向隊(duì)列(deque)顶霞。
注意LinkedList沒有同步方法肄程。如果多個(gè)線程同時(shí)訪問一個(gè)List锣吼,則必須自己實(shí)現(xiàn)訪問同步。一種解決方法是在創(chuàng)建List時(shí)構(gòu)造一個(gè)同步的List:
List list = Collections.synchronizedList(new LinkedList(…));
34蓝厌、如果HashMap的大小超過了負(fù)載因子(load factor)定義的容量玄叠,怎么辦?
答:HashMap默認(rèn)的負(fù)載因子大小為0.75拓提,也就是說读恃,當(dāng)一個(gè)map填滿了75%的空間的時(shí)候,和其它集合類(如ArrayList等)一樣代态,將會創(chuàng)建原來HashMap大小的兩倍的數(shù)組寺惫,來重新調(diào)整map的大小,并將原來的對象放入新的數(shù)組中蹦疑。這個(gè)過程叫作rehashing西雀,因?yàn)樗{(diào)用hash方法找到新的bucket位置。
35歉摧、ConcurrentHashMap和Hashtable的區(qū)別艇肴?
答:它們都可以用于多線程的環(huán)境,但是當(dāng)Hashtable的大小增加到一定的時(shí)候叁温,性能會急劇下降再悼,因?yàn)榈鷷r(shí)需要被鎖定很長的時(shí)間。因?yàn)镃oncurrentHashMap引入了分割(segmentation)膝但,不論它變得多么大冲九,僅僅需要鎖定map的某個(gè)部分,而其它的線程不需要等到迭代完成才能訪問map跟束。簡而言之莺奸,在迭代的過程中,ConcurrentHashMap僅僅鎖定map的某個(gè)部分泳炉,而Hashtable則會鎖定整個(gè)map憾筏。
36、Collection 和 Collections的區(qū)別花鹅?
答:Collection是集合類的上級接口,繼承與他的接口主要有Set 和List.
Collections是針對集合類的一個(gè)幫助類,他提供一系列靜態(tài)方法實(shí)現(xiàn)對各種集合的搜索氧腰、排序、線程安全化等操作刨肃。
37古拴、簡單描述java集合類?
答:java集合類都繼承于Collection接口真友,主要有三種:List黄痪、Set和Map。
-- List有子類LinkedList盔然、ArrayList和Vector
ArrayList: 元素單個(gè)桅打,效率高是嗜,多用于查詢 。
Vector: 元素單個(gè)挺尾,線程安全鹅搪,多用于查詢。
LinkedList: 元素單個(gè)遭铺,多用于插入和刪除
-- Set有子類HashSet丽柿、SortedSet和TreeSet
-- Map有子類HashMap、HashTable魂挂、LinkedHashMap和WeakHashMap
HashMap: 元素成對甫题,元素可為空。
HashTable: 元素成對涂召,線程安全坠非,元素不可為空。
LinkedHashMap:它保留插入的順序芹扭,如果需要輸出的順序和輸入時(shí)的相同麻顶,那么就選用LinkedHashMap。
WeakHashMap: 是一種改進(jìn)的HashMap舱卡,它對key實(shí)行“弱引用”,如果一個(gè)key不再被外部所引用队萤,那么該key可以被轮锥。
38、當(dāng)一個(gè)線程進(jìn)入一個(gè)對象的一個(gè)synchronized方法后要尔,其它線程是否可進(jìn)入此對象的其它方法舍杜?
答:分幾種情況:
-- 其他方法前是否加了synchronized關(guān)鍵字,如果沒加赵辕,則能既绩。
-- 如果這個(gè)方法內(nèi)部調(diào)用了wait,則可以進(jìn)入其他synchronized方法还惠。
-- 如果其他個(gè)方法都加了synchronized關(guān)鍵字饲握,并且內(nèi)部沒有調(diào)用wait,則不能蚕键。
39救欧、sleep() 和 wait() 有什么區(qū)別?
答:sleep就是當(dāng)前線程主動讓出cpu锣光,cpu去執(zhí)行其他線程笆怠,在sleep指定的時(shí)間過后,cpu才會回到這個(gè)線程上繼續(xù)往下執(zhí)行誊爹,如果當(dāng)前線程進(jìn)入了同步鎖蹬刷,sleep方法并不會釋放鎖瓢捉,即使當(dāng)前線程使用sleep方法讓出了cpu,但其他被同步鎖擋住了的線程也無法得到執(zhí)行办成。
wait是指在一個(gè)已經(jīng)進(jìn)入了同步鎖的線程內(nèi)泡态,讓自己讓出同步鎖,以便其他正在等待此鎖的線程可以得到同步鎖并運(yùn)行诈火,只有其他線程調(diào)用了notify方法(notify并不釋放鎖兽赁,只是處于wait狀態(tài)的線程可以去參與獲得鎖的競爭了,但不是馬上得到鎖冷守,因?yàn)殒i還在當(dāng)前線程中刀崖,如果notify方法后面的代碼還有很多,需要這些代碼執(zhí)行完后才會釋放鎖)拍摇,值得注意的是亮钦,notify方法只是隨機(jī)通知一個(gè)wait狀態(tài)的線程,notifyAll方法可以通知所有wait該鎖的線程充活。
例子:
運(yùn)行結(jié)果:
enter thread1...
thread1 is waiting
enter thread2...
thread2 is waiting
enter thread3...
thread2 notify other thread can release wait status..
thread3 is sleeping ten millisecond...
thread3 is going on...
thread3 is being over!
thread1 is going on...
thread1 is being over!
如果調(diào)用的是notify蜂莉,則結(jié)果如上,thread1執(zhí)行完畢混卵,thread2一直被掛著映穗。
40、Java中的volatile 變量是什么幕随?
答:volatile是一個(gè)特殊的修飾符蚁滋,只有成員變量才能使用它。在Java并發(fā)程序缺少同步類的情況下赘淮,多線程對成員變量的操作對其它線程是透明的辕录。volatile變量可以保證下一個(gè)讀取操作會在前一個(gè)寫操作之后發(fā)生。
41梢卸、 什么是線程安全走诞?Vector是一個(gè)線程安全類嗎?
答:如果你的代碼所在的進(jìn)程中有多個(gè)線程在同時(shí)運(yùn)行蛤高,而這些線程可能會同時(shí)運(yùn)行這段代碼蚣旱。如果每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的襟齿,就是線程安全的姻锁。一個(gè)線程安全的計(jì)數(shù)器類的同一個(gè)實(shí)例對象在被多個(gè)線程使用的情況下也不會出現(xiàn)計(jì)算失誤。很顯然你可以將集合類分成兩組猜欺,線程安全和非線程安全的位隶。Vector 是用同步方法來實(shí)現(xiàn)線程安全的, 而和它相似的ArrayList不是線程安全的。
42开皿、什么是ThreadLocal變量涧黄?
答:ThreadLocal用于創(chuàng)建線程的本地變量篮昧,我們知道一個(gè)對象的所有線程會共享它的全局變量,所以這些變量不是線程安全的笋妥,我們可以使用同步技術(shù)懊昨。但是當(dāng)我們不想使用同步的時(shí)候,我們可以選擇ThreadLocal變量春宣。每個(gè)線程都會擁有他們自己的Thread變量酵颁,它們可以使用get()\set()方法去獲取他們的默認(rèn)值或者在線程內(nèi)部改變他們的值。
43月帝、 Java中interrupted 和 isInterruptedd方法的區(qū)別躏惋?
答:interrupted() 和 isInterrupted()的主要區(qū)別是前者會將中斷狀態(tài)清除而后者不會。Java多線程的中斷機(jī)制是用內(nèi)部標(biāo)識來實(shí)現(xiàn)的嚷辅,調(diào)用Thread.interrupt()來中斷一個(gè)線程就會設(shè)置中斷標(biāo)識為true簿姨。當(dāng)中斷線程調(diào)用靜態(tài)方法Thread.interrupted()來檢查中斷狀態(tài)時(shí),中斷狀態(tài)會被清零簸搞。而非靜態(tài)方法isInterrupted()用來查詢其它線程的中斷狀態(tài)且不會改變中斷狀態(tài)標(biāo)識扁位。簡單的說就是任何拋出InterruptedException異常的方法都會將中斷狀態(tài)清零。無論如何趁俊,一個(gè)線程的中斷狀態(tài)有有可能被其它線程調(diào)用中斷來改變域仇。
44、什么是線程池寺擂? 為什么要使用它殉簸?
答:創(chuàng)建線程要花費(fèi)昂貴的資源和時(shí)間,如果任務(wù)來了才創(chuàng)建線程那么響應(yīng)時(shí)間會變長沽讹,而且一個(gè)進(jìn)程能創(chuàng)建的線程數(shù)有限。為了避免這些問題武鲁,在程序啟動的時(shí)候就創(chuàng)建若干線程來響應(yīng)處理爽雄,它們被稱為線程池,里面的線程叫工作線程沐鼠。從JDK1.5開始挚瘟,Java API提供了Executor框架讓你可以創(chuàng)建不同的線程池。比如單線程池饲梭,每次處理一個(gè)任務(wù)乘盖;數(shù)目固定的線程池或者是緩存線程池(一個(gè)適合很多生存期短的任務(wù)的程序的可擴(kuò)展線程池)。
45憔涉、有三個(gè)線程T1订框,T2,T3兜叨,怎么確保它們按順序執(zhí)行穿扳?
答:在多線程中有多種方法讓線程按特定順序執(zhí)行衩侥,你可以用線程類的join()方法在一個(gè)線程中啟動另一個(gè)線程,另外一個(gè)線程完成該線程繼續(xù)執(zhí)行矛物。為了確保三個(gè)線程的順序你應(yīng)該先啟動最后一個(gè)(T3調(diào)用T2茫死,T2調(diào)用T1),這樣T1就會先完成而T3最后完成履羞。
46峦萎、什么是服務(wù)端包含(Server Side Include)?
答:服務(wù)端包含(SSI)是一種簡單的解釋型服務(wù)端腳本語言忆首,大多數(shù)時(shí)候僅用在Web上爱榔,用servlet標(biāo)簽嵌入進(jìn)來。SSI最常用的場景把一個(gè)或多個(gè)文件包含到Web服務(wù)器的一個(gè)Web頁面中雄卷。當(dāng)瀏覽器訪問Web頁面的時(shí)候搓蚪,Web服務(wù)器會用對應(yīng)的servlet產(chǎn)生的文本來替換Web頁面中的servlet標(biāo)簽。
47丁鹉、HTTP響應(yīng)的結(jié)構(gòu)是怎么樣的妒潭?
答:HTTP響應(yīng)由三個(gè)部分組成:
狀態(tài)碼(Status Code):描述了響應(yīng)的狀態(tài)〈眨可以用來檢查是否成功的完成了請求雳灾。請求失敗的情況下,狀態(tài)碼可用來找出失敗的原因冯凹。如果Servlet沒有返回狀態(tài)碼谎亩,默認(rèn)會返回成功的狀態(tài)碼HttpServletResponse.SC_OK。
HTTP頭部(HTTP Header):它們包含了更多關(guān)于響應(yīng)的信息宇姚。比如:頭部可以指定認(rèn)為響應(yīng)過期的過期日期匈庭,或者是指定用來給用戶安全的傳輸實(shí)體內(nèi)容的編碼格式。
主體(Body):它包含了響應(yīng)的內(nèi)容浑劳。它可以包含HTML代碼阱持,圖片,等等魔熏。主體是由傳輸在HTTP消息中緊跟在頭部后面的數(shù)據(jù)字節(jié)組成的衷咽。
48、什么是cookie蒜绽?session和cookie有什么區(qū)別镶骗?
答:cookie是Web服務(wù)器發(fā)送給瀏覽器的一塊信息。瀏覽器會在本地文件中給每一個(gè)Web服務(wù)器存儲cookie躲雅。以后瀏覽器在給特定的Web服務(wù)器發(fā)請求的時(shí)候鼎姊,同時(shí)會發(fā)送所有為該服務(wù)器存儲的cookie。下面列出了session和cookie的區(qū)別:
無論客戶端瀏覽器做怎么樣的設(shè)置,session都應(yīng)該能正常工作此蜈〖春幔客戶端可以選擇禁用cookie,但是裆赵,session仍然是能夠工作的东囚,因?yàn)榭蛻舳藷o法禁用服務(wù)端的session。
在存儲的數(shù)據(jù)量方面session和cookies也是不一樣的战授。session能夠存儲任意的Java對象页藻,cookie只能存儲String類型的對象。
49植兰、使用Spring框架的好處是什么份帐?
答:輕量:Spring 是輕量的,基本的版本大約2MB楣导。
控制反轉(zhuǎn):Spring通過控制反轉(zhuǎn)實(shí)現(xiàn)了松散耦合废境,對象們給出它們的依賴,而不是創(chuàng)建或查找依賴的對象們筒繁。
面向切面的編程(AOP):Spring支持面向切面的編程噩凹,并且把應(yīng)用業(yè)務(wù)邏輯和系統(tǒng)服務(wù)分開。
容器:Spring 包含并管理應(yīng)用中對象的生命周期和配置毡咏。
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 異常恢总。
50迎罗、解釋Spring框架中bean的生命周期?
答:-- Spring容器 從XML 文件中讀取bean的定義片仿,并實(shí)例化bean佳谦。
-- Spring根據(jù)bean的定義填充所有的屬性。
-- 如果bean實(shí)現(xiàn)了BeanNameAware 接口滋戳,Spring 傳遞bean 的ID 到 setBeanName方法。
-- 如果Bean 實(shí)現(xiàn)了 BeanFactoryAware 接口啥刻, Spring傳遞beanfactory 給setBeanFactory 方法奸鸯。
-- 如果有任何與bean相關(guān)聯(lián)的BeanPostProcessors,Spring會在postProcesserBeforeInitialization()方法內(nèi)調(diào)用它們可帽。
-- 如果bean實(shí)現(xiàn)IntializingBean了娄涩,調(diào)用它的afterPropertySet方法,如果bean聲明了初始化方法,調(diào)用此初始化方法蓄拣。
-- 如果有BeanPostProcessors 和bean 關(guān)聯(lián)扬虚,這些bean的postProcessAfterInitialization() 方法將被調(diào)用。
-- 如果bean實(shí)現(xiàn)了 DisposableBean球恤,它將調(diào)用destroy()方法辜昵。
51、Spring框架的事務(wù)管理有哪些優(yōu)點(diǎn)咽斧?
答:-- 它為不同的事務(wù)API 如 JTA堪置,JDBC,Hibernate张惹,JPA 和JDO舀锨,提供一個(gè)不變的編程模式。
-- 它為編程式事務(wù)管理提供了一套簡單的API而不是一些復(fù)雜的事務(wù)API如
-- 它支持聲明式事務(wù)管理宛逗。
-- 它和Spring各種數(shù)據(jù)訪問抽象層很好得集成坎匿。
52、Spring MVC工作機(jī)制雷激?
答: 1.spring mvc請所有的請求都提交給DispatcherServlet,它會委托應(yīng)用系統(tǒng)的其他模塊負(fù)責(zé)負(fù)責(zé)對請求進(jìn)行真正的處理工作替蔬。 2.DispatcherServlet查詢一個(gè)或多個(gè)HandlerMapping,找到處理請求的Controller. 3.DispatcherServlet請請求提交到目標(biāo)Controller 4.Controller進(jìn)行業(yè)務(wù)邏輯處理后,會返回一個(gè)ModelAndView 5.Dispathcher查詢一個(gè)或多個(gè)ViewResolver視圖解析器,找到ModelAndView對象指定的視圖對象 6.視圖對象負(fù)責(zé)渲染返回給客戶端侥锦。
53进栽、Hibernate的一級緩存與二級緩存的區(qū)別?
答:一級緩存就是Session級別的緩存恭垦,一個(gè)Session做了一個(gè)查詢操作快毛,它會把這個(gè)操作的結(jié)果放在一級緩存中,如果短時(shí)間內(nèi)這個(gè)session(一定要同一個(gè)session)又做了同一個(gè)操作番挺,那么hibernate直接從一級緩存中拿唠帝,而不會再去連數(shù)據(jù)庫,取數(shù)據(jù)玄柏。二級緩存就是SessionFactory級別的緩存襟衰,顧名思義,就是查詢的時(shí)候會把查詢結(jié)果緩存到二級緩存中粪摘,如果同一個(gè)sessionFactory創(chuàng)建的某個(gè)session執(zhí)行了相同的操作瀑晒,hibernate就會從二級緩存中拿結(jié)果,而不會再去連接數(shù)據(jù)庫徘意。
54苔悦、Spring框架中的單例Beans是線程安全的么?
答:Spring框架并沒有對單例bean進(jìn)行任何多線程的封裝處理椎咧。關(guān)于單例bean的線程安全和并發(fā)問題需要開發(fā)者自行去搞定玖详。但實(shí)際上,大部分的Spring bean并沒有可變的狀態(tài)(比如Serview類和DAO類),所以在某種程度上說Spring的單例bean是線程安全的蟋座。如果你的bean有多種狀態(tài)的話(比如 View Model 對象)拗踢,就需要自行保證線程安全。
55、Spring事務(wù)是如何傳播的?
答:1) PROPAGATION_REQUIRED 洞焙,默認(rèn)的spring事務(wù)傳播級別侄柔,使用該級別的特點(diǎn)是,如果上下文中已經(jīng)存在事務(wù),那么就加入到事務(wù)中執(zhí)行,如果當(dāng)前上下文中不存在事務(wù),則新建事務(wù)執(zhí)行庵芭。所以這個(gè)級別通常能滿足處理大多數(shù)的業(yè)務(wù)場景。
2)PROPAGATION_SUPPORTS 雀监,從字面意思就知道双吆,supports,支持会前,該傳播級別的特點(diǎn)是好乐,如果上下文存在事務(wù),則支持事務(wù)加入事務(wù)瓦宜,如果沒有事務(wù)蔚万,則使用非事務(wù)的方式執(zhí)行。所以說临庇,并非所有的包在transactionTemplate.execute中的代碼都會有事務(wù)支持反璃。這個(gè)通常是用來處理那些并非原子性的非核心業(yè)務(wù)邏輯操作。應(yīng)用場景較少假夺。
3)PROPAGATION_MANDATORY 淮蜈, 該級別的事務(wù)要求上下文中必須要存在事務(wù),否則就會拋出異常已卷!配置該方式的傳播級別是有效的控制上下文調(diào)用代碼遺漏添加事務(wù)控制的保證手段梧田。比如一段代碼不能單獨(dú)被調(diào)用執(zhí)行,但是一旦被調(diào)用侧蘸,就必須有事務(wù)包含的情況裁眯,就可以使用這個(gè)傳播級別。
4)PROPAGATION_REQUIRES_NEW 讳癌,從字面即可知道未状,new,每次都要一個(gè)新事務(wù)析桥,該傳播級別的特點(diǎn)是,每次都會新建一個(gè)事務(wù),并且同時(shí)將上下文中的事務(wù)掛起泡仗,執(zhí)行當(dāng)前新建事務(wù)完成以后埋虹,上下文事務(wù)恢復(fù)再執(zhí)行。
這是一個(gè)很有用的傳播級別娩怎,舉一個(gè)應(yīng)用場景:現(xiàn)在有一個(gè)發(fā)送100個(gè)紅包的操作搔课,在發(fā)送之前,要做一些系統(tǒng)的初始化截亦、驗(yàn)證爬泥、數(shù)據(jù)記錄操作,然后發(fā)送100封紅包崩瓤,然后再記錄發(fā)送日志袍啡,發(fā)送日志要求100%的準(zhǔn)確,如果日志不準(zhǔn)確却桶,那么整個(gè)父事務(wù)邏輯需要回滾境输。
怎么處理整個(gè)業(yè)務(wù)需求呢?就是通過這個(gè)PROPAGATION_REQUIRES_NEW 級別的事務(wù)傳播控制就可以完成颖系。發(fā)送紅包的子事務(wù)不會直接影響到父事務(wù)的提交和回滾嗅剖。
5)PROPAGATION_NOT_SUPPORTED ,這個(gè)也可以從字面得知嘁扼,not supported 信粮,不支持,當(dāng)前級別的特點(diǎn)就是上下文中存在事務(wù)趁啸,則掛起事務(wù)强缘,執(zhí)行當(dāng)前邏輯,結(jié)束后恢復(fù)上下文的事務(wù)莲绰。
這個(gè)級別有什么好處欺旧?可以幫助你將事務(wù)極可能的縮小。我們知道一個(gè)事務(wù)越大蛤签,它存在的風(fēng)險(xiǎn)也就越多辞友。所以在處理事務(wù)的過程中,要保證盡可能的縮小范圍震肮。比如一段代碼称龙,是每次邏輯操作都必須調(diào)用的,比如循環(huán)1000次的某個(gè)非核心業(yè)務(wù)邏輯操作戳晌。這樣的代碼如果包在事務(wù)中鲫尊,勢必造成事務(wù)太大,導(dǎo)致出現(xiàn)一些難以考慮周全的異常情況沦偎。所以這個(gè)事務(wù)這個(gè)級別的傳播級別就派上用場了疫向。用當(dāng)前級別的事務(wù)模板抱起來就可以了咳蔚。
6)PROPAGATION_NEVER ,該事務(wù)更嚴(yán)格搔驼,上面一個(gè)事務(wù)傳播級別只是不支持而已谈火,有事務(wù)就掛起,而PROPAGATION_NEVER傳播級別要求上下文中不能存在事務(wù)舌涨,一旦有事務(wù)糯耍,就拋出runtime異常,強(qiáng)制停止執(zhí)行囊嘉!這個(gè)級別上輩子跟事務(wù)有仇温技。
7)PROPAGATION_NESTED ,字面也可知道扭粱,nested舵鳞,嵌套級別事務(wù)。該傳播級別特征是焊刹,如果上下文中存在事務(wù)系任,則嵌套事務(wù)執(zhí)行,如果不存在事務(wù)虐块,則新建事務(wù)俩滥。
56、Spring AOP實(shí)現(xiàn)原理贺奠?
答:java動態(tài)代理霜旧。接下來描述動態(tài)代理(考生自由發(fā)揮)。
57儡率、Spring是如何管理事務(wù)的挂据?
答:Spring既支持編程式事務(wù)管理(也稱編碼式事務(wù)),也支持聲明式的事務(wù)管理
-- 編程式事務(wù)管理:將事務(wù)管理代碼嵌入到業(yè)務(wù)方法中來控制事務(wù)的提交和回滾儿普,在編程式事務(wù)中崎逃,必須在每個(gè)業(yè)務(wù)操作中包含額外的事務(wù)管理代碼。
-- 聲明式事務(wù)管理建立在AOP之上的眉孩。其本質(zhì)是對方法前后進(jìn)行攔截个绍,然后在目標(biāo)方法開始之前創(chuàng)建或者加入一個(gè)事務(wù),在執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行情況提交或者回滾事務(wù)浪汪。聲明式事務(wù)最大的優(yōu)點(diǎn)就是不需要通過編程的方式管理事務(wù)巴柿,這樣就不需要在業(yè)務(wù)邏輯代碼中摻雜事務(wù)管理的代碼,只需在配置文件中做相關(guān)的事務(wù)規(guī)則聲明(或通過基于@Transactional注解的方式)死遭,便可以將事務(wù)規(guī)則應(yīng)用到業(yè)務(wù)邏輯中广恢。顯然聲明式事務(wù)管理要優(yōu)于編程式事務(wù)管理,這正是spring倡導(dǎo)的非侵入式的開發(fā)方式呀潭。聲明式事務(wù)管理使業(yè)務(wù)代碼不受污染钉迷,一個(gè)普通的POJO對象至非,只要加上注解就可以獲得完全的事務(wù)支持。和編程式事務(wù)相比糠聪,聲明式事務(wù)唯一不足地方是睡蟋,后者的最細(xì)粒度只能作用到方法級別,無法做到像編程式事務(wù)那樣可以作用到代碼塊級別枷颊。但是即便有這樣的需求,也存在很多變通的方法该面,比如夭苗,可以將需要進(jìn)行事務(wù)管理的代碼塊獨(dú)立為方法等等。
聲明式事務(wù)管理也有兩種常用的方式隔缀,一種是基于tx和aop名字空間的xml配置文件题造,另一種就是基于@Transactional注解。顯然基于注解的方式更簡單易用猾瘸,更清爽界赔。
@Transactional屬性
屬性 類型 描述
value String 可選的限定描述符,指定使用的事務(wù)管理器
propagation enum: Propagation 可選的事務(wù)傳播行為設(shè)置
isolation enum: Isolation 可選的事務(wù)隔離級別設(shè)置
readOnly boolean 讀寫或只讀事務(wù)牵触,默認(rèn)讀寫
timeout int (in seconds granularity) 事務(wù)超時(shí)時(shí)間設(shè)置
rollbackFor Class對象數(shù)組淮悼,必須繼承自Throwable 導(dǎo)致事務(wù)回滾的異常類數(shù)組
rollbackForClassName 類名數(shù)組,必須繼承自Throwable 導(dǎo)致事務(wù)回滾的異常類名字?jǐn)?shù)組
noRollbackFor Class對象數(shù)組揽思,必須繼承自Throwable 不會導(dǎo)致事務(wù)回滾的異常類數(shù)組
noRollbackForClassName 類名數(shù)組袜腥,必須繼承自Throwable 不會導(dǎo)致事務(wù)回滾的異常類名字?jǐn)?shù)組
58、Spring MVC的工作原理钉汗?
答:
客戶端請求提交到DispatcherServlet
由DispatcherServlet控制器查詢一個(gè)或多個(gè)HandlerMapping羹令,找到處理請求的Controller
DispatcherServlet將請求提交到Controller
Controller調(diào)用業(yè)務(wù)邏輯處理后,返回ModelAndView
DispatcherServlet查詢一個(gè)或多個(gè)ViewResoler視圖解析器损痰,找到ModelAndView指定的視圖
視圖負(fù)責(zé)將結(jié)果顯示到客戶端
59福侈、Spring MVC與Struts有什么區(qū)別?
答:
機(jī)制:spring mvc的入口是servlet卢未,而struts2是filter肪凛,這樣就導(dǎo)致了二者的機(jī)制不同。
性能:spring會稍微比struts快尝丐。spring mvc是基于方法的設(shè)計(jì)显拜,而sturts是基于類,每次發(fā)一次請求都會實(shí)例一個(gè)action爹袁,每個(gè)action都會被注入屬性远荠,而spring基于方法,粒度更細(xì)失息,但要小心把握像在servlet控制數(shù)據(jù)一樣譬淳。spring3 mvc是方法級別的攔截档址,攔截到方法后根據(jù)參數(shù)上的注解,把request數(shù)據(jù)注入進(jìn)去邻梆,在spring3 mvc中守伸,一個(gè)方法對應(yīng)一個(gè)request上下文。而struts2框架是類級別的攔截浦妄,每次來了請求就創(chuàng)建一個(gè)Action尼摹,然后調(diào)用setter getter方法把request中的數(shù)據(jù)注入;struts2實(shí)際上是通 setter getter方法與request打交道的剂娄;struts2中蠢涝,一個(gè)Action對象對應(yīng)一個(gè)request上下文。
參數(shù)傳遞:struts是在接受參數(shù)的時(shí)候阅懦,可以用屬性來接受參數(shù)和二,這就說明參數(shù)是讓多個(gè)方法共享的。
設(shè)計(jì)思想上:struts更加符合oop(面向?qū)ο缶幊?的編程思想耳胎, spring就比較謹(jǐn)慎惯吕,在servlet上擴(kuò)展。
intercepter的實(shí)現(xiàn)機(jī)制:struts有自己的interceptor機(jī)制怕午,spring mvc用的是獨(dú)立的AOP方式废登。這樣導(dǎo)致struts的配置文件量還是比spring mvc大,雖然struts的配置能繼承诗轻,所以我覺得論使用上來講钳宪,spring mvc使用更加簡潔,開發(fā)效率Spring MVC確實(shí)比struts2高扳炬。spring mvc是方法級別的攔截吏颖,一個(gè)方法對應(yīng)一個(gè)request上下文,而方法同時(shí)又跟一個(gè)url對應(yīng)恨樟,所以說從架構(gòu)本身上spring3 mvc就容易實(shí)現(xiàn)restful url半醉。struts2是類級別的攔截,一個(gè)類對應(yīng)一個(gè)request上下文劝术;實(shí)現(xiàn)restful url要費(fèi)勁缩多,因?yàn)閟truts2 action的一個(gè)方法可以對應(yīng)一個(gè)url;而其類屬性卻被所有方法共享养晋,這也就無法用注解或其他方式標(biāo)識其所屬方法了衬吆。spring3 mvc的方法之間基本上獨(dú)立的,獨(dú)享request response數(shù)據(jù)绳泉,請求數(shù)據(jù)通過參數(shù)獲取逊抡,處理結(jié)果通過ModelMap交回給框架方法之間不共享變量,而struts2搞的就比較亂零酪,雖然方法之間也是獨(dú)立的冒嫡,但其所有Action變量是共享的拇勃,這不會影響程序運(yùn)行,卻給我們編碼孝凌,讀程序時(shí)帶來麻煩方咆。
另外,spring3 mvc的驗(yàn)證也是一個(gè)亮點(diǎn)蟀架,支持JSR303瓣赂,處理ajax的請求更是方便,只需一個(gè)注解@ResponseBody 片拍,然后直接返回響應(yīng)文本即可钩述。
60、簡單描述Spring的啟動過程穆碎?
答:
首先,對于一個(gè)web應(yīng)用职恳,其部署在web容器中所禀,web容器提供其一個(gè)全局的上下文環(huán)境,這個(gè)上下文就是ServletContext放钦,其為后面的spring IoC容器提供宿主環(huán)境色徘;
其次,在web.xml中會提供有contextLoaderListener操禀。在web容器啟動時(shí)褂策,會觸發(fā)容器初始化事件,此時(shí)contextLoaderListener會監(jiān)聽到這個(gè)事件颓屑,其contextInitialized方法會被調(diào)用斤寂,在這個(gè)方法中,spring會初始化一個(gè)啟動上下文揪惦,這個(gè)上下文被稱為根上下文遍搞,即WebApplicationContext,這是一個(gè)接口類器腋,確切的說溪猿,其實(shí)際的實(shí)現(xiàn)類是XmlWebApplicationContext。這個(gè)就是spring的IoC容器纫塌,其對應(yīng)的Bean定義的配置由web.xml中的context-param標(biāo)簽指定诊县。在這個(gè)IoC容器初始化完畢后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE為屬性Key措左,將其存儲到ServletContext中依痊,便于獲取媳荒;
再次抗悍,contextLoaderListener監(jiān)聽器初始化完畢后驹饺,開始初始化web.xml中配置的Servlet,這個(gè)servlet可以配置多個(gè)缴渊,以最常見的DispatcherServlet為例赏壹,這個(gè)servlet實(shí)際上是一個(gè)標(biāo)準(zhǔn)的前端控制器,用以轉(zhuǎn)發(fā)衔沼、匹配蝌借、處理每個(gè)servlet請求。DispatcherServlet上下文在初始化的時(shí)候會建立自己的IoC上下文指蚁,用以持有spring mvc相關(guān)的bean菩佑。在建立DispatcherServlet自己的IoC上下文時(shí),會利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先從ServletContext中獲取之前的根上下文(即WebApplicationContext)作為自己上下文的parent上下文凝化。有了這個(gè)parent上下文之后稍坯,再初始化自己持有的上下文。這個(gè)DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到搓劫,大概的工作就是初始化處理器映射瞧哟、視圖解析等。這個(gè)servlet自己持有的上下文默認(rèn)實(shí)現(xiàn)類也是mlWebApplicationContext枪向。初始化完畢后勤揩,spring以與servlet的名字相關(guān)(此處不是簡單的以servlet名為Key,而是通過一些轉(zhuǎn)換秘蛔,具體可自行查看源碼)的屬性為屬性Key陨亡,也將其存到ServletContext中,以便后續(xù)使用深员。這樣每個(gè)servlet就持有自己的上下文负蠕,即擁有自己獨(dú)立的bean空間,同時(shí)各個(gè)servlet共享相同的bean倦畅,即根上下文(第2步中初始化的上下文)定義的那些bean虐急。
61、Mybatis中#與$的區(qū)別滔迈?
答:1. #將傳入的數(shù)據(jù)都當(dāng)成一個(gè)字符串止吁,會對自動傳入的數(shù)據(jù)加一個(gè)雙引號,類似于PreparedStatmte的動態(tài)綁定參數(shù)燎悍。
$將傳入的數(shù)據(jù)直接顯示生成在sql中敬惦,類似于直接拼SQL。
#
方式能夠很大程度防止sql注入谈山。
4.$
方式無法防止Sql注入俄删。
5.$方式一般用于傳入數(shù)據(jù)庫對象,例如傳入表名。
6.一般能用#的就別用$畴椰。
62臊诊、簡單描述Mybatis緩存?
答:mybaits提供一級緩存斜脂,和二級緩存抓艳。
-- 一級緩存是SqlSession級別的緩存。在操作數(shù)據(jù)庫時(shí)需要構(gòu)造 sqlSession對象帚戳,在對象中有一個(gè)(內(nèi)存區(qū)域)數(shù)據(jù)結(jié)構(gòu)(HashMap)用于存儲緩存數(shù)據(jù)玷或。不同的sqlSession之間的緩存數(shù)據(jù)區(qū)域(HashMap)是互相不影響的。一級緩存的作用域是同一個(gè)SqlSession片任,在同一個(gè)sqlSession中兩次執(zhí)行相同的sql語句偏友,第一次執(zhí)行完畢會將數(shù)據(jù)庫中查詢的數(shù)據(jù)寫到緩存(內(nèi)存),第二次會從緩存中獲取數(shù)據(jù)將不再從數(shù)據(jù)庫查詢对供,從而提高查詢效率位他。當(dāng)一個(gè)sqlSession結(jié)束后該sqlSession中的一級緩存也就不存在了。Mybatis默認(rèn)開啟一級緩存产场。
-- 二級緩存是mapper級別的緩存棱诱,多個(gè)SqlSession去操作同一個(gè)Mapper的sql語句,多個(gè)SqlSession去操作數(shù)據(jù)庫得到數(shù)據(jù)會存在二級緩存區(qū)域涝动,多個(gè)SqlSession可以共用二級緩存,二級緩存是跨SqlSession的炬灭,是多個(gè)SqlSession共享的醋粟,其作用域是mapper的同一個(gè)namespace,不同的sqlSession兩次執(zhí)行相同namespace下的sql語句且向sql中傳遞參數(shù)也相同即最終執(zhí)行相同的sql語句重归,第一次執(zhí)行完畢會將數(shù)據(jù)庫中查詢的數(shù)據(jù)寫到緩存(內(nèi)存)米愿,第二次會從緩存中獲取數(shù)據(jù)將不再從數(shù)據(jù)庫查詢,從而提高查詢效率鼻吮。Mybatis默認(rèn)沒有開啟二級緩存需要在setting全局參數(shù)中配置開啟二級緩存育苟。
63、使用Mybatis的好處椎木?
答:mybatis把sql語句從Java源程序中獨(dú)立出來违柏,放在單獨(dú)的XML文件中編寫,給程序的維護(hù)帶來了很大便利香椎。mybatis封裝了底層JDBC API的調(diào)用細(xì)節(jié)漱竖,并能自動將結(jié)果集轉(zhuǎn)換成Java Bean對象,大大簡化了Java數(shù)據(jù)庫編程的重復(fù)工作畜伐。因?yàn)閙ybatis需要程序員自己去編寫sql語句馍惹,程序員可以結(jié)合數(shù)據(jù)庫自身的特點(diǎn)靈活控制sql語句,因此能夠?qū)崿F(xiàn)比hibernate等全自動orm框架更高的查詢效率,能夠完成復(fù)雜查詢万矾。
64悼吱、Mybatis是如何與java bean進(jìn)行映射的?
答:使用resultMap關(guān)鍵字映射數(shù)據(jù)庫字段和java字段良狈。比如:
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
type關(guān)鍵字為對應(yīng)的java bean的路徑后添,使用result把具體的字段綁定到j(luò)ava bean中。
65们颜、Mybatis中如何實(shí)現(xiàn)一對一吕朵、一對多的?
答:“關(guān)聯(lián)”(association)實(shí)現(xiàn)一對一的關(guān)系窥突,“集合”(collection)實(shí)現(xiàn)一對多的關(guān)系努溃。
66、MySQL都有哪些存儲引擎阻问,有什么區(qū)別梧税?
答:主要存儲引擎:MyISAM、InnoDB称近、MEMORY和MERGE第队,MySQL5.5以后默認(rèn)使用InnoDB存儲引擎。
-- MyISAM不支持事務(wù)刨秆、也不支持外鍵凳谦,但其訪問速度快,對事務(wù)完整性沒有要求衡未。
-- InnoDB存儲引擎提供了具有提交尸执、回滾和崩潰恢復(fù)能力的事務(wù)安全。但是比起MyISAM存儲引擎缓醋,InnoDB寫的處理效率差一些并且會占用更多的磁盤空間以保留數(shù)據(jù)和索引如失。
-- MEMORY存儲引擎使用存在內(nèi)存中的內(nèi)容來創(chuàng)建表。每個(gè)MEMORY表只實(shí)際對應(yīng)一個(gè)磁盤文件送粱。MEMORY類型的表訪問非常得快褪贵,因?yàn)樗臄?shù)據(jù)是放在內(nèi)存中的,并且默認(rèn)使用HASH索引抗俄。但是一旦服務(wù)關(guān)閉脆丁,表中的數(shù)據(jù)就會丟失掉。
-- MERGE存儲引擎是一組MyISAM表的組合动雹,這些MyISAM表必須結(jié)構(gòu)完全相同偎快。MERGE表本身沒有數(shù)據(jù),對MERGE類型的表進(jìn)行查詢洽胶、更新晒夹、刪除的操作裆馒,就是對內(nèi)部的MyISAM表進(jìn)行的。
67丐怯、說說常見的數(shù)據(jù)庫優(yōu)化喷好?
答:1>創(chuàng)建索引,建索引的字段應(yīng)滿足以下條件:
-- 字段出現(xiàn)在查詢條件中读跷,并且查詢條件可以使用索引梗搅;
-- 語句執(zhí)行頻率高,一天會有幾千次以上效览;
-- 通過字段條件可篩選的記錄集很形耷小;
2>使用分頁
3>只返回必要字段以減少數(shù)據(jù)在網(wǎng)絡(luò)上傳輸開銷
4>使用BATCH操作丐枉,減少交互的次數(shù)
5>加大fetch_size哆键,這樣可以減少結(jié)果數(shù)據(jù)傳輸?shù)慕换ゴ螖?shù)及服務(wù)器數(shù)據(jù)準(zhǔn)備時(shí)間,提高性能瘦锹。