Java面試題庫與答案解析-17、Java 最常見的 200+ 面試題匯總+答案總結(jié)匯總_第1頁
Java面試題庫與答案解析-17、Java 最常見的 200+ 面試題匯總+答案總結(jié)匯總_第2頁
Java面試題庫與答案解析-17、Java 最常見的 200+ 面試題匯總+答案總結(jié)匯總_第3頁
Java面試題庫與答案解析-17、Java 最常見的 200+ 面試題匯總+答案總結(jié)匯總_第4頁
Java面試題庫與答案解析-17、Java 最常見的 200+ 面試題匯總+答案總結(jié)匯總_第5頁
已閱讀5頁,還剩39頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

在本篇文章開始之前,我想先來回答一個問題:我為什么要寫這樣一篇關(guān)于面試的文章?原因有三個:第一,我想為每一個為夢想時刻準(zhǔn)備著的“有心人”,盡一份自己的力量,提供一份高度精華的Java面試清單;第二,目前市面上的面試題不是答案不準(zhǔn)確就是內(nèi)容覆蓋面太窄,所以提供一份經(jīng)典而又準(zhǔn)確的面試題是非常有必要的;第三,本文會對部分面試題提供詳細(xì)解讀和代碼案例,讓讀者知其然并知其所以然,從而學(xué)到更多的知識。或許這份面試題還不足以囊括所有Java問題,但有了它,我相信你一定不會“敗”的很慘,因為有了它,足以應(yīng)對目前市面上絕大部分的Java面試了,因為這篇文章不論是從深度還是廣度上來講,都已經(jīng)囊括了非常多的知識點了。凡事預(yù)則立,不預(yù)則廢。能讀到這里的人,我相信都是這個世界上的“有心人”,還是那句老話:上天不負(fù)有心人!我相信你的每一步努力,都會收獲意想不到的回報。適宜閱讀人群

需要面試的初/中/高級Java程序員

想要查漏補(bǔ)缺的人

想要不斷完善和擴(kuò)充自己Java技術(shù)棧的人

Java面試官

閱讀建議

本文會按技能模塊劃分文章段落,每個模塊里的內(nèi)容,從易到難依次進(jìn)行排序,各模塊之間不存在互相關(guān)聯(lián)的關(guān)系,讀者可選擇文章順序閱讀或者跳躍式閱讀。包含的模塊

本文分為十九個模塊,分別是:Java基礎(chǔ)、容器、多線程、反射、對象拷貝、JavaWeb、異常、網(wǎng)絡(luò)、設(shè)計模式、Spring/SpringMVC、SpringBoot/SpringCloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、MySQL、Redis、JVM,如下圖所示:共包含208道面試題,本文的宗旨是為讀者朋友們整理一份詳實而又權(quán)威的面試清單,下面一起進(jìn)入主題吧。Java基礎(chǔ)JDK和JRE有什么區(qū)別?

JDK:JavaDevelopmentKit的簡稱,Java開發(fā)工具包,提供了Java的開發(fā)環(huán)境和運(yùn)行環(huán)境。

JRE:JavaRuntimeEnvironment的簡稱,Java運(yùn)行環(huán)境,為Java的運(yùn)行提供了所需環(huán)境。

具體來說JDK其實包含了JRE,同時還包含了編譯Java源碼的編譯器Javac,還包含了很多Java程序調(diào)試和分析的工具。簡單來說:如果你需要運(yùn)行Java程序,只需安裝JRE就可以了,如果你需要編寫Java程序,需要安裝JDK。==和equals的區(qū)別是什么?

==解讀對于基本類型和引用類型==的作用效果是不同的,如下所示:基本類型:比較的是值是否相同;

引用類型:比較的是引用是否相同;

代碼示例:Stringx=“string”;

Stringy=“string”;

Stringz=newString(“string”);

System.out.println(xy);//true

System.out.println(xz);//false

System.out.println(x.equals(y));//true

System.out.println(x.equals(z));//true

代碼解讀:因為x和y指向的是同一個引用,所以==也是true,而newString()方法則重寫開辟了內(nèi)存空間,所以==結(jié)果為false,而equals比較的一直是值,所以結(jié)果都為true。equals解讀equals本質(zhì)上就是==,只不過String和Integer等重寫了equals方法,把它變成了值比較??聪旅娴拇a就明白了。首先來看默認(rèn)情況下equals比較一個有相同值的對象,代碼如下:classCat{

publicCat(Stringname){

=name;

}privateStringname;publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}}Catc1=newCat(“王磊”);

Catc2=newCat(“王磊”);

System.out.println(c1.equals(c2));//false

輸出結(jié)果出乎我們的意料,竟然是false?這是怎么回事,看了equals源碼就知道了,源碼如下:publicbooleanequals(Objectobj){

return(this==obj);

}

原來equals本質(zhì)上就是==。那問題來了,兩個相同值的String對象,為什么返回的是true?代碼如下:Strings1=newString(“老王”);

Strings2=newString(“老王”);

System.out.println(s1.equals(s2));//true

同樣的,當(dāng)我們進(jìn)入String的equals方法,找到了答案,代碼如下:publicbooleanequals(ObjectanObject){

if(this==anObject){

returntrue;

}

if(anObjectinstanceofString){

StringanotherString=(String)anObject;

intn=value.length;

if(n==anotherString.value.length){

charv1[]=value;

charv2[]=anotherString.value;

inti=0;

while(n--!=0){

if(v1[i]!=v2[i])

returnfalse;

i++;

}

returntrue;

}

}

returnfalse;

}

原來是String重寫了Object的equals方法,把引用比較改成了值比較??偨Y(jié):==對于基本類型來說是值比較,對于引用類型來說是比較的是引用;而equals默認(rèn)情況下是引用比較,只是很多類重新了equals方法,比如String、Integer等把它變成了值比較,所以一般情況下equals比較的是值是否相等。兩個對象的hashCode()相同,則equals()也一定為true,對嗎?

不對,兩個對象的hashCode()相同,equals()不一定true。代碼示例:Stringstr1=“通話”;

Stringstr2=“重地”;

System.out.println(String.format(“str1:%d|str2:%d”,str1.hashCode(),str2.hashCode()));

System.out.println(str1.equals(str2));

執(zhí)行的結(jié)果:str1:1179395|str2:1179395false

代碼解讀:很顯然“通話”和“重地”的hashCode()相同,然而equals()則為false,因為在散列表中,hashCode()相等即兩個鍵值對的哈希值相等,然而哈希值相等,并不一定能得出鍵值對相等。final在Java中有什么作用?

final修飾的類叫最終類,該類不能被繼承。

final修飾的方法不能被重寫。

final修飾的變量叫常量,常量必須初始化,初始化之后值就不能被修改。Java中的Math.round(-1.5)等于多少?

等于-1,Math.round四舍五入大于0.5向上取整的。String屬于基礎(chǔ)的數(shù)據(jù)類型嗎?

String不屬于基礎(chǔ)類型,基礎(chǔ)類型有8種:byte、boolean、char、short、int、float、long、double,而String屬于對象。Java中操作字符串都有哪些類?它們之間有什么區(qū)別?

操作字符串的類有:String、StringBuffer、StringBuilder。String和StringBuffer、StringBuilder的區(qū)別在于String聲明的是不可變的對象,每次操作都會生成新的String對象,然后將指針指向新的String對象,而StringBuffer、StringBuilder可以在原有對象的基礎(chǔ)上進(jìn)行操作,所以在經(jīng)常改變字符串內(nèi)容的情況下最好不要使用String。StringBuffer和StringBuilder最大的區(qū)別在于,StringBuffer是線程安全的,而StringBuilder是非線程安全的,但StringBuilder的性能卻高于StringBuffer,所以在單線程環(huán)境下推薦使用StringBuilder,多線程環(huán)境下推薦使用StringBuffer。Stringstr="i"與Stringstr=newString(“i”)一樣嗎?

不一樣,因為內(nèi)存的分配方式不一樣。Stringstr="i"的方式,Java虛擬機(jī)會將其分配到常量池中;而Stringstr=newString(“i”)則會被分到堆內(nèi)存中。如何將字符串反轉(zhuǎn)?

使用StringBuilder或者stringBuffer的reverse()方法。示例代碼://StringBufferreverse

StringBufferstringBuffer=newStringBuffer();

stringBuffer.append(“abcdefg”);

System.out.println(stringBuffer.reverse());//gfedcba

//StringBuilderreverse

StringBuilderstringBuilder=newStringBuilder();

stringBuilder.append(“abcdefg”);

System.out.println(stringBuilder.reverse());//gfedcba

10.String類的常用方法都有那些?

indexOf():返回指定字符的索引。

charAt():返回指定索引處的字符。

replace():字符串替換。

trim():去除字符串兩端空白。

split():分割字符串,返回一個分割后的字符串?dāng)?shù)組。

getBytes():返回字符串的byte類型數(shù)組。

length():返回字符串長度。

toLowerCase():將字符串轉(zhuǎn)成小寫字母。

toUpperCase():將字符串轉(zhuǎn)成大寫字符。

substring():截取字符串。

equals():字符串比較。

11.抽象類必須要有抽象方法嗎?

不需要,抽象類不一定非要有抽象方法。示例代碼:abstractclassCat{

publicstaticvoidsayHi(){

System.out.println(“hi~”);

}

}

上面代碼,抽象類并沒有抽象方法但完全可以正常運(yùn)行。普通類和抽象類有哪些區(qū)別?

普通類不能包含抽象方法,抽象類可以包含抽象方法。

抽象類不能直接實例化,普通類可以直接實例化。抽象類能使用final修飾嗎?

不能,定義抽象類就是讓其他類繼承的,如果定義為final該類就不能被繼承,這樣彼此就會產(chǎn)生矛盾,所以final不能修飾抽象類,如下圖所示,編輯器也會提示錯誤信息:編譯器保存圖接口和抽象類有什么區(qū)別?

默認(rèn)方法實現(xiàn):抽象類可以有默認(rèn)的方法實現(xiàn);接口不能有默認(rèn)的方法實現(xiàn)。

實現(xiàn):抽象類的子類使用extends來繼承;接口必須使用implements來實現(xiàn)接口。

構(gòu)造函數(shù):抽象類可以有構(gòu)造函數(shù);接口不能有。

main方法:抽象類可以有main方法,并且我們能運(yùn)行它;接口不能有main方法。

實現(xiàn)數(shù)量:類可以實現(xiàn)很多個接口;但是只能繼承一個抽象類。

訪問修飾符:接口中的方法默認(rèn)使用public修飾;抽象類中的方法可以是任意訪問修飾符。Java中IO流分為幾種?

按功能來分:輸入流(input)、輸出流(output)。按類型來分:字節(jié)流和字符流。字節(jié)流和字符流的區(qū)別是:字節(jié)流按8位傳輸以字節(jié)為單位輸入輸出數(shù)據(jù),字符流按16位傳輸以字符為單位輸入輸出數(shù)據(jù)。BIO、NIO、AIO有什么區(qū)別?

BIO:BlockIO同步阻塞式IO,就是我們平常使用的傳統(tǒng)IO,它的特點是模式簡單使用方便,并發(fā)處理能力低。

NIO:NewIO同步非阻塞IO,是傳統(tǒng)IO的升級,客戶端和服務(wù)器端通過Channel(通道)通訊,實現(xiàn)了多路復(fù)用。

AIO:AsynchronousIO是NIO的升級,也叫NIO2,實現(xiàn)了異步非堵塞IO,異步IO的操作基于事件和回調(diào)機(jī)制。Files的常用方法都有哪些?

Files.exists():檢測文件路徑是否存在。

Files.createFile():創(chuàng)建文件。

Files.createDirectory():創(chuàng)建文件夾。

Files.delete():刪除一個文件或目錄。

Files.copy():復(fù)制文件。

Files.move():移動文件。

Files.size():查看文件個數(shù)。

Files.read():讀取文件。

Files.write():寫入文件。

容器Java容器都有哪些?

Java容器分為Collection和Map兩大類,其下又有很多子類,如下所示:Collection

List

ArrayList

LinkedList

Vector

Stack

Set

HashSet

LinkedHashSet

TreeSet

Map

HashMap

LinkedHashMap

TreeMap

ConcurrentHashMap

Hashtable

19.Collection和Collections有什么區(qū)別?

Collection是一個集合接口,它提供了對集合對象進(jìn)行基本操作的通用接口方法,所有集合都是它的子類,比如List、Set等。

Collections是一個包裝類,包含了很多靜態(tài)方法,不能被實例化,就像一個工具類,比如提供的排序方法:Collections.sort(list)。

20.List、Set、Map之間的區(qū)別是什么?

List、Set、Map的區(qū)別主要體現(xiàn)在兩個方面:元素是否有序、是否允許元素重復(fù)。三者之間的區(qū)別,如下表:區(qū)別圖HashMap和Hashtable有什么區(qū)別?

存儲:HashMap運(yùn)行key和value為null,而Hashtable不允許。

線程安全:Hashtable是線程安全的,而HashMap是非線程安全的。

推薦使用:在Hashtable的類注釋可以看到,Hashtable是保留類不建議使用,推薦在單線程環(huán)境下使用HashMap替代,如果需要多線程使用則用ConcurrentHashMap替代。如何決定使用HashMap還是TreeMap?

對于在Map中插入、刪除、定位一個元素這類操作,HashMap是最好的選擇,因為相對而言HashMap的插入會更快,但如果你要對一個key集合進(jìn)行有序的遍歷,那TreeMap是更好的選擇。說一下HashMap的實現(xiàn)原理?

HashMap基于Hash算法實現(xiàn)的,我們通過put(key,value)存儲,get(key)來獲取。當(dāng)傳入key時,HashMap會根據(jù)key.hashCode()計算出hash值,根據(jù)hash值將value保存在bucket里。當(dāng)計算出的hash值相同時,我們稱之為hash沖突,HashMap的做法是用鏈表和紅黑樹存儲相同hash值的value。當(dāng)hash沖突的個數(shù)比較少時,使用鏈表否則使用紅黑樹。說一下HashSet的實現(xiàn)原理?

HashSet是基于HashMap實現(xiàn)的,HashSet底層使用HashMap來保存所有元素,因此HashSet的實現(xiàn)比較簡單,相關(guān)HashSet的操作,基本上都是直接調(diào)用底層HashMap的相關(guān)方法來完成,HashSet不允許重復(fù)的值。ArrayList和LinkedList的區(qū)別是什么?

數(shù)據(jù)結(jié)構(gòu)實現(xiàn):ArrayList是動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu)實現(xiàn),而LinkedList是雙向鏈表的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)。

隨機(jī)訪問效率:ArrayList比LinkedList在隨機(jī)訪問的時候效率要高,因為LinkedList是線性的數(shù)據(jù)存儲方式,所以需要移動指針從前往后依次查找。

增加和刪除效率:在非首尾的增加和刪除操作,LinkedList要比ArrayList效率要高,因為ArrayList增刪操作要影響數(shù)組內(nèi)的其他數(shù)據(jù)的下標(biāo)。

綜合來說,在需要頻繁讀取集合中的元素時,更推薦使用ArrayList,而在插入和刪除操作較多時,更推薦使用LinkedList。如何實現(xiàn)數(shù)組和List之間的轉(zhuǎn)換?

數(shù)組轉(zhuǎn)List:使用Arrays.asList(array)進(jìn)行轉(zhuǎn)換。

List轉(zhuǎn)數(shù)組:使用List自帶的toArray()方法。

代碼示例://listtoarray

Listlist=newArrayList();

list.add(“王磊”);

list.add(“的博客”);

list.toArray();

//arraytolist

String[]array=newString[]{“王磊”,“的博客”};

Arrays.asList(array);

27.ArrayList和Vector的區(qū)別是什么?

線程安全:Vector使用了Synchronized來實現(xiàn)線程同步,是線程安全的,而ArrayList是非線程安全的。

性能:ArrayList在性能方面要優(yōu)于Vector。

擴(kuò)容:ArrayList和Vector都會根據(jù)實際的需要動態(tài)的調(diào)整容量,只不過在Vector擴(kuò)容每次會增加1倍,而ArrayList只會增加50%。

28.Array和ArrayList有何區(qū)別?

Array可以存儲基本數(shù)據(jù)類型和對象,ArrayList只能存儲對象。

Array是指定固定大小的,而ArrayList大小是自動擴(kuò)展的。

Array內(nèi)置方法沒有ArrayList多,比如addAll、removeAll、iteration等方法只有ArrayList有。

29.在Queue中poll()和remove()有什么區(qū)別?

相同點:都是返回第一個元素,并在隊列中刪除返回的對象。

不同點:如果沒有元素poll()會返回null,而remove()會直接拋出NoSuchElementException異常。

代碼示例:Queuequeue=newLinkedList();

queue.offer(“string”);//add

System.out.println(queue.poll());

System.out.println(queue.remove());

System.out.println(queue.size());

30.哪些集合類是線程安全的?

Vector、Hashtable、Stack都是線程安全的,而像HashMap則是非線程安全的,不過在JDK1.5之后隨著Java.util.concurrent并發(fā)包的出現(xiàn),它們也有了自己對應(yīng)的線程安全類,比如HashMap對應(yīng)的線程安全類就是ConcurrentHashMap。迭代器Iterator是什么?

Iterator接口提供遍歷任何Collection的接口。我們可以從一個Collection中使用迭代器方法來獲取迭代器實例。迭代器取代了Java集合框架中的Enumeration,迭代器允許調(diào)用者在迭代過程中移除元素。Iterator怎么使用?有什么特點?

Iterator使用代碼如下:Listlist=newArrayList<>();

Iteratorit=list.iterator();

while(it.hasNext()){

Stringobj=it.next();

System.out.println(obj);

}

Iterator的特點是更加安全,因為它可以確保,在當(dāng)前遍歷的集合元素被更改的時候,就會拋出ConcurrentModificationException異常。Iterator和ListIterator有什么區(qū)別?

Iterator可以遍歷Set和List集合,而ListIterator只能遍歷List。

Iterator只能單向遍歷,而ListIterator可以雙向遍歷(向前/后遍歷)。

ListIterator從Iterator接口繼承,然后添加了一些額外的功能,比如添加一個元素、替換一個元素、獲取前面或后面元素的索引位置。怎么確保一個集合不能被修改?

可以使用Collections.unmodifiableCollection(Collectionc)方法來創(chuàng)建一個只讀集合,這樣改變集合的任何操作都會拋出Java.lang.UnsupportedOperationException異常。示例代碼如下:Listlist=newArrayList<>();

list.add(“x”);

Collectionclist=Collections.unmodifiableCollection(list);

clist.add(“y”);//運(yùn)行時此行報錯

System.out.println(list.size());

多線程

35.并行和并發(fā)有什么區(qū)別?

并行:多個任務(wù)在同一個CPU核上,按細(xì)分的時間片輪流(交替)執(zhí)行,從邏輯上來看那些任務(wù)是同時執(zhí)行。

并發(fā):多個處理器或多核處理器同時處理多個任務(wù)。

如下圖:并發(fā)和并行并發(fā)=兩個隊列和一臺咖啡機(jī)。并行=兩個隊列和兩臺咖啡機(jī)。線程和進(jìn)程的區(qū)別?

一個程序下至少有一個進(jìn)程,一個進(jìn)程下至少有一個線程,一個進(jìn)程下也可以有多個線程來增加程序的執(zhí)行速度。守護(hù)線程是什么?

守護(hù)線程是運(yùn)行在后臺的一種特殊進(jìn)程。它獨(dú)立于控制終端并且周期性地執(zhí)行某種任務(wù)或等待處理某些發(fā)生的事件。在Java中垃圾回收線程就是特殊的守護(hù)線程。創(chuàng)建線程有哪幾種方式?

創(chuàng)建線程有三種方式:繼承Thread重新run方法;

實現(xiàn)Runnable接口;

實現(xiàn)Callable接口。

39.說一下runnable和callable有什么區(qū)別?

runnable沒有返回值,callable可以拿到有返回值,callable可以看作是runnable的補(bǔ)充。線程有哪些狀態(tài)?

線程的狀態(tài):NEW尚未啟動

RUNNABLE正在執(zhí)行中

BLOCKED阻塞的(被同步鎖或者IO鎖阻塞)

WAITING永久等待狀態(tài)

TIMED_WAITING等待指定的時間重新被喚醒的狀態(tài)

TERMINATED執(zhí)行完成

41.sleep()和wait()有什么區(qū)別?

類的不同:sleep()來自Thread,wait()來自O(shè)bject。

釋放鎖:sleep()不釋放鎖;wait()釋放鎖。

用法不同:sleep()時間到會自動恢復(fù);wait()可以使用notify()/notifyAll()直接喚醒。

42.notify()和notifyAll()有什么區(qū)別?

notifyAll()會喚醒所有的線程,notify()之后喚醒一個線程。notifyAll()調(diào)用后,會將全部線程由等待池移到鎖池,然后參與鎖的競爭,競爭成功則繼續(xù)執(zhí)行,如果不成功則留在鎖池等待鎖被釋放后再次參與競爭。而notify()只會喚醒一個線程,具體喚醒哪一個線程由虛擬機(jī)控制。線程的run()和start()有什么區(qū)別?

start()方法用于啟動線程,run()方法用于執(zhí)行線程的運(yùn)行時代碼。run()可以重復(fù)調(diào)用,而start()只能調(diào)用一次。創(chuàng)建線程池有哪幾種方式?

線程池創(chuàng)建有七種方式,最核心的是最后一種:newSingleThreadExecutor():它的特點在于工作線程數(shù)目被限制為1,操作一個無界的工作隊列,所以它保證了所有任務(wù)的都是被順序執(zhí)行,最多會有一個任務(wù)處于活動狀態(tài),并且不允許使用者改動線程池實例,因此可以避免其改變線程數(shù)目;newCachedThreadPool():它是一種用來處理大量短時間工作任務(wù)的線程池,具有幾個鮮明特點:它會試圖緩存線程并重用,當(dāng)無緩存線程可用時,就會創(chuàng)建新的工作線程;如果線程閑置的時間超過60秒,則被終止并移出緩存;長時間閑置時,這種線程池,不會消耗什么資源。其內(nèi)部使用SynchronousQueue作為工作隊列;newFixedThreadPool(intnThreads):重用指定數(shù)目(nThreads)的線程,其背后使用的是無界的工作隊列,任何時候最多有nThreads個工作線程是活動的。這意味著,如果任務(wù)數(shù)量超過了活動隊列數(shù)目,將在工作隊列中等待空閑線程出現(xiàn);如果有工作線程退出,將會有新的工作線程被創(chuàng)建,以補(bǔ)足指定的數(shù)目nThreads;newSingleThreadScheduledExecutor():創(chuàng)建單線程池,返回ScheduledExecutorService,可以進(jìn)行定時或周期性的工作調(diào)度;newScheduledThreadPool(intcorePoolSize):和newSingleThreadScheduledExecutor()類似,創(chuàng)建的是個ScheduledExecutorService,可以進(jìn)行定時或周期性的工作調(diào)度,區(qū)別在于單一工作線程還是多個工作線程;newWorkStealingPool(intparallelism):這是一個經(jīng)常被人忽略的線程池,Java8才加入這個創(chuàng)建方法,其內(nèi)部會構(gòu)建ForkJoinPool,利用Work-Stealing算法,并行地處理任務(wù),不保證處理順序;ThreadPoolExecutor():是最原始的線程池創(chuàng)建,上面1-3創(chuàng)建方式都是對ThreadPoolExecutor的封裝。線程池都有哪些狀態(tài)?

RUNNING:這是最正常的狀態(tài),接受新的任務(wù),處理等待隊列中的任務(wù)。

SHUTDOWN:不接受新的任務(wù)提交,但是會繼續(xù)處理等待隊列中的任務(wù)。

STOP:不接受新的任務(wù)提交,不再處理等待隊列中的任務(wù),中斷正在執(zhí)行任務(wù)的線程。

TIDYING:所有的任務(wù)都銷毀了,workCount為0,線程池的狀態(tài)在轉(zhuǎn)換為TIDYING狀態(tài)時,會執(zhí)行鉤子方法terminated()。

TERMINATED:terminated()方法結(jié)束后,線程池的狀態(tài)就會變成這個。線程池中submit()和execute()方法有什么區(qū)別?

execute():只能執(zhí)行Runnable類型的任務(wù)。

submit():可以執(zhí)行Runnable和Callable類型的任務(wù)。

Callable類型的任務(wù)可以獲取執(zhí)行的返回值,而Runnable執(zhí)行無返回值。在Java程序中怎么保證多線程的運(yùn)行安全?

方法一:使用安全類,比如Java.util.concurrent下的類。

方法二:使用自動鎖synchronized。

方法三:使用手動鎖Lock。

手動鎖Java示例代碼如下:Locklock=newReentrantLock();

lock.lock();

try{

System.out.println(“獲得鎖”);

}catch(Exceptione){

//TODO:handleexception

}finally{

System.out.println(“釋放鎖”);

lock.unlock();

}

48.多線程中synchronized鎖升級的原理是什么?

synchronized鎖升級原理:在鎖對象的對象頭里面有一個threadid字段,在第一次訪問的時候threadid為空,jvm讓其持有偏向鎖,并將threadid設(shè)置為其線程id,再次進(jìn)入的時候會先判斷threadid是否與其線程id一致,如果一致則可以直接使用此對象,如果不一致,則升級偏向鎖為輕量級鎖,通過自旋循環(huán)一定次數(shù)來獲取鎖,執(zhí)行一定次數(shù)之后,如果還沒有正常獲取到要使用的對象,此時就會把鎖從輕量級升級為重量級鎖,此過程就構(gòu)成了synchronized鎖的升級。鎖的升級的目的:鎖升級是為了減低了鎖帶來的性能消耗。在Java6之后優(yōu)化synchronized的實現(xiàn)方式,使用了偏向鎖升級為輕量級鎖再升級到重量級鎖的方式,從而減低了鎖帶來的性能消耗。什么是死鎖?

當(dāng)線程A持有獨(dú)占鎖a,并嘗試去獲取獨(dú)占鎖b的同時,線程B持有獨(dú)占鎖b,并嘗試獲取獨(dú)占鎖a的情況下,就會發(fā)生AB兩個線程由于互相持有對方需要的鎖,而發(fā)生的阻塞現(xiàn)象,我們稱為死鎖。怎么防止死鎖?

盡量使用tryLock(longtimeout,TimeUnitunit)的方法(ReentrantLock、ReentrantReadWriteLock),設(shè)置超時時間,超時可以退出防止死鎖。

盡量使用Java.util.concurrent并發(fā)類代替自己手寫鎖。

盡量降低鎖的使用粒度,盡量不要幾個功能用同一把鎖。

盡量減少同步的代碼塊。ThreadLocal是什么?有哪些使用場景?

ThreadLocal為每個使用該變量的線程提供獨(dú)立的變量副本,所以每一個線程都可以獨(dú)立地改變自己的副本,而不會影響其它線程所對應(yīng)的副本。ThreadLocal的經(jīng)典使用場景是數(shù)據(jù)庫連接和session管理等。說一下synchronized底層實現(xiàn)原理?

synchronized是由一對monitorenter/monitorexit指令實現(xiàn)的,monitor對象是同步的基本實現(xiàn)單元。在Java6之前,monitor的實現(xiàn)完全是依靠操作系統(tǒng)內(nèi)部的互斥鎖,因為需要進(jìn)行用戶態(tài)到內(nèi)核態(tài)的切換,所以同步操作是一個無差別的重量級操作,性能也很低。但在Java6的時候,Java虛擬機(jī)對此進(jìn)行了大刀闊斧地改進(jìn),提供了三種不同的monitor實現(xiàn),也就是常說的三種不同的鎖:偏向鎖(BiasedLocking)、輕量級鎖和重量級鎖,大大改進(jìn)了其性能。synchronized和volatile的區(qū)別是什么?

volatile是變量修飾符;synchronized是修飾類、方法、代碼段。

volatile僅能實現(xiàn)變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性。

volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。synchronized和Lock有什么區(qū)別?

synchronized可以給類、方法、代碼塊加鎖;而lock只能給代碼塊加鎖。

synchronized不需要手動獲取鎖和釋放鎖,使用簡單,發(fā)生異常會自動釋放鎖,不會造成死鎖;而lock需要自己加鎖和釋放鎖,如果使用不當(dāng)沒有unLock()去釋放鎖就會造成死鎖。

通過Lock可以知道有沒有成功獲取鎖,而synchronized卻無法辦到。synchronized和ReentrantLock區(qū)別是什么?

synchronized早期的實現(xiàn)比較低效,對比ReentrantLock,大多數(shù)場景性能都相差較大,但是在Java6中對synchronized進(jìn)行了非常多的改進(jìn)。主要區(qū)別如下:ReentrantLock使用起來比較靈活,但是必須有釋放鎖的配合動作;

ReentrantLock必須手動獲取與釋放鎖,而synchronized不需要手動釋放和開啟鎖;

ReentrantLock只適用于代碼塊鎖,而synchronized可用于修飾方法、代碼塊等。

volatile標(biāo)記的變量不會被編譯器優(yōu)化;synchronized標(biāo)記的變量可以被編譯器優(yōu)化。

56.說一下atomic的原理?

atomic主要利用CAS(CompareAndWwap)和volatile和native方法來保證原子操作,從而避免synchronized的高開銷,執(zhí)行效率大為提升。反射

57.什么是反射?

反射是在運(yùn)行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用它的任意一個方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為Java語言的反射機(jī)制。什么是Java序列化?什么情況下需要序列化?

Java序列化是為了保存各種對象在內(nèi)存中的狀態(tài),并且可以把保存的對象狀態(tài)再讀出來。以下情況需要使用Java序列化:想把的內(nèi)存中的對象狀態(tài)保存到一個文件中或者數(shù)據(jù)庫中時候;

想用套接字在網(wǎng)絡(luò)上傳送對象的時候;

想通過RMI(遠(yuǎn)程方法調(diào)用)傳輸對象的時候。

59.動態(tài)代理是什么?有哪些應(yīng)用?

動態(tài)代理是運(yùn)行時動態(tài)生成代理類。動態(tài)代理的應(yīng)用有springaop、hibernate數(shù)據(jù)查詢、測試框架的后端mock、rpc,Java注解對象獲取等。怎么實現(xiàn)動態(tài)代理?

JDK原生動態(tài)代理和cglib動態(tài)代理。JDK原生動態(tài)代理是基于接口實現(xiàn)的,而cglib是基于繼承當(dāng)前類的子類實現(xiàn)的。對象拷貝

61.為什么要使用克???

克隆的對象可能包含一些已經(jīng)修改過的屬性,而new出來的對象的屬性都還是初始化時候的值,所以當(dāng)需要一個新的對象來保存當(dāng)前對象的“狀態(tài)”就靠克隆方法了。如何實現(xiàn)對象克???

實現(xiàn)Cloneable接口并重寫Object類中的clone()方法。

實現(xiàn)Serializable接口,通過對象的序列化和反序列化實現(xiàn)克隆,可以實現(xiàn)真正的深度克隆。深拷貝和淺拷貝區(qū)別是什么?

淺克隆:當(dāng)對象被復(fù)制時只復(fù)制它本身和其中包含的值類型的成員變量,而引用類型的成員對象并沒有復(fù)制。

深克隆:除了對象本身被復(fù)制外,對象所包含的所有成員變量也將復(fù)制。

JavaWebJSP和servlet有什么區(qū)別?

JSP是servlet技術(shù)的擴(kuò)展,本質(zhì)上就是servlet的簡易方式。servlet和JSP最主要的不同點在于,servlet的應(yīng)用邏輯是在Java文件中,并且完全從表示層中的html里分離開來,而JSP的情況是Java和html可以組合成一個擴(kuò)展名為JSP的文件。JSP側(cè)重于視圖,servlet主要用于控制邏輯。JSP有哪些內(nèi)置對象?作用分別是什么?

JSP有9大內(nèi)置對象:request:封裝客戶端的請求,其中包含來自get或post請求的參數(shù);

response:封裝服務(wù)器對客戶端的響應(yīng);

pageContext:通過該對象可以獲取其他對象;

session:封裝用戶會話的對象;

application:封裝服務(wù)器運(yùn)行環(huán)境的對象;

out:輸出服務(wù)器響應(yīng)的輸出流對象;

config:Web應(yīng)用的配置對象;

page:JSP頁面本身(相當(dāng)于Java程序中的this);

exception:封裝頁面拋出異常的對象。

66.說一下JSP的4種作用域?

page:代表與一個頁面相關(guān)的對象和屬性。

request:代表與客戶端發(fā)出的一個請求相關(guān)的對象和屬性。一個請求可能跨越多個頁面,涉及多個Web組件;需要在頁面顯示的臨時數(shù)據(jù)可以置于此作用域。

session:代表與某個用戶與服務(wù)器建立的一次會話相關(guān)的對象和屬性。跟某個用戶相關(guān)的數(shù)據(jù)應(yīng)該放在用戶自己的session中。

application:代表與整個Web應(yīng)用程序相關(guān)的對象和屬性,它實質(zhì)上是跨越整個Web應(yīng)用程序,包括多個頁面、請求和會話的一個全局作用域。

67.session和cookie有什么區(qū)別?

存儲位置不同:session存儲在服務(wù)器端;cookie存儲在瀏覽器端。

安全性不同:cookie安全性一般,在瀏覽器存儲,可以被偽造和修改。

容量和個數(shù)限制:cookie有容量限制,每個站點下的cookie也有個數(shù)限制。

存儲的多樣性:session可以存儲在Redis中、數(shù)據(jù)庫中、應(yīng)用程序中;而cookie只能存儲在瀏覽器中。

68.說一下session的工作原理?

session的工作原理是客戶端登錄完成之后,服務(wù)器會創(chuàng)建對應(yīng)的session,session創(chuàng)建完之后,會把session的id發(fā)送給客戶端,客戶端再存儲到瀏覽器中。這樣客戶端每次訪問服務(wù)器時,都會帶著sessionid,服務(wù)器拿到sessionid之后,在內(nèi)存找到與之對應(yīng)的session這樣就可以正常工作了。如果客戶端禁止cookie能實現(xiàn)session還能用嗎?

可以用,session只是依賴cookie存儲sessionid,如果cookie被禁用了,可以使用url中添加sessionid的方式保證session能正常使用。springmvc和struts的區(qū)別是什么?

攔截級別:struts2是類級別的攔截;springmvc是方法級別的攔截。

數(shù)據(jù)獨(dú)立性:springmvc的方法之間基本上獨(dú)立的,獨(dú)享request和response數(shù)據(jù),請求數(shù)據(jù)通過參數(shù)獲取,處理結(jié)果通過ModelMap交回給框架,方法之間不共享變量;而struts2雖然方法之間也是獨(dú)立的,但其所有action變量是共享的,這不會影響程序運(yùn)行,卻給我們編碼和讀程序時帶來了一定的麻煩。

攔截機(jī)制:struts2有以自己的interceptor機(jī)制,springmvc用的是獨(dú)立的aop方式,這樣導(dǎo)致struts2的配置文件量比springmvc大。

對ajax的支持:springmvc集成了ajax,所有ajax使用很方便,只需要一個注解@ResponseBody就可以實現(xiàn)了;而struts2一般需要安裝插件或者自己寫代碼才行。如何避免SQL注入?

使用預(yù)處理PreparedStatement。

使用正則表達(dá)式過濾掉字符中的特殊字符。什么是XSS攻擊,如何避免?

XSS攻擊:即跨站腳本攻擊,它是Web程序中常見的漏洞。原理是攻擊者往Web頁面里插入惡意的腳本代碼(css代碼、Javascript代碼等),當(dāng)用戶瀏覽該頁面時,嵌入其中的腳本代碼會被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的,如盜取用戶cookie、破壞頁面結(jié)構(gòu)、重定向到其他網(wǎng)站等。預(yù)防XSS的核心是必須對輸入的數(shù)據(jù)做過濾處理。什么是CSRF攻擊,如何避免?

CSRF:Cross-SiteRequestForgery(中文:跨站請求偽造),可以理解為攻擊者盜用了你的身份,以你的名義發(fā)送惡意請求,比如:以你名義發(fā)送郵件、發(fā)消息、購買商品,虛擬貨幣轉(zhuǎn)賬等。防御手段:驗證請求來源地址;

關(guān)鍵操作添加驗證碼;

在請求地址添加token并驗證。

異常

74.throw和throws的區(qū)別?

throw:是真實拋出一個異常。

throws:是聲明可能會拋出一個異常。

75.final、finally、finalize有什么區(qū)別?

final:是修飾符,如果修飾類,此類不能被繼承;如果修飾方法和變量,則表示此方法和此變量不能在被改變,只能使用。

finally:是try{}catch{}finally{}最后一部分,表示不論發(fā)生任何情況都會執(zhí)行,finally部分可以省略,但如果finally部分存在,則一定會執(zhí)行finally里面的代碼。

finalize:是Object類的一個方法,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法。

76.try-catch-finally中哪個部分可以省略?

try-catch-finally其中catch和finally都可以被省略,但是不能同時省略,也就是說有try的時候,必須后面跟一個catch或者finally。try-catch-finally中,如果catch中return了,finally還會執(zhí)行嗎?

finally一定會執(zhí)行,即使是catch中return了,catch中的return會等finally中的代碼執(zhí)行完之后,才會執(zhí)行。常見的異常類有哪些?

NullPointerException空指針異常

ClassNotFoundException指定類不存在

NumberFormatException字符串轉(zhuǎn)換為數(shù)字異常

IndexOutOfBoundsException數(shù)組下標(biāo)越界異常

ClassCastException數(shù)據(jù)類型轉(zhuǎn)換異常

FileNotFoundException文件未找到異常

NoSuchMethodException方法不存在異常

IOExceptionIO異常

SocketExceptionSocket異常

網(wǎng)絡(luò)http響應(yīng)碼301和302代表的是什么?有什么區(qū)別?

301:永久重定向。302:暫時重定向。它們的區(qū)別是,301對搜索引擎優(yōu)化(SEO)更加有利;302有被提示為網(wǎng)絡(luò)攔截的風(fēng)險。forward和redirect的區(qū)別?

forward是轉(zhuǎn)發(fā)和redirect是重定向:地址欄url顯示:fowardurl不會發(fā)生改變,redirecturl會發(fā)生改變;

數(shù)據(jù)共享:forward可以共享request里的數(shù)據(jù),redirect不能共享;

效率:forward比redirect效率高。

81.簡述tcp和udp的區(qū)別?

tcp和udp是OSI模型中的運(yùn)輸層中的協(xié)議。tcp提供可靠的通信傳輸,而udp則常被用于讓廣播和細(xì)節(jié)控制交給應(yīng)用的通信傳輸。兩者的區(qū)別大致如下:tcp面向連接,udp面向非連接即發(fā)送數(shù)據(jù)前不需要建立鏈接;

tcp提供可靠的服務(wù)(數(shù)據(jù)傳輸),udp無法保證;

tcp面向字節(jié)流,udp面向報文;

tcp數(shù)據(jù)傳輸慢,udp數(shù)據(jù)傳輸快;

82.tcp為什么要三次握手,兩次不行嗎?為什么?

如果采用兩次握手,那么只要服務(wù)器發(fā)出確認(rèn)數(shù)據(jù)包就會建立連接,但由于客戶端此時并未響應(yīng)服務(wù)器端的請求,那此時服務(wù)器端就會一直在等待客戶端,這樣服務(wù)器端就白白浪費(fèi)了一定的資源。若采用三次握手,服務(wù)器端沒有收到來自客戶端的再此確認(rèn),則就會知道客戶端并沒有要求建立請求,就不會浪費(fèi)服務(wù)器的資源。說一下tcp粘包是怎么產(chǎn)生的?

tcp粘包可能發(fā)生在發(fā)送端或者接收端,分別來看兩端各種產(chǎn)生粘包的原因:發(fā)送端粘包:發(fā)送端需要等緩沖區(qū)滿才發(fā)送出去,造成粘包;

接收方粘包:接收方不及時接收緩沖區(qū)的包,造成多個包接收。

84.OSI的七層模型都有哪些?

物理層:利用傳輸介質(zhì)為數(shù)據(jù)鏈路層提供物理連接,實現(xiàn)比特流的透明傳輸。

數(shù)據(jù)鏈路層:負(fù)責(zé)建立和管理節(jié)點間的鏈路。

網(wǎng)絡(luò)層:通過路由選擇算法,為報文或分組通過通信子網(wǎng)選擇最適當(dāng)?shù)穆窂健?/p>

傳輸層:向用戶提供可靠的端到端的差錯和流量控制,保證報文的正確傳輸。

會話層:向兩個實體的表示層提供建立和使用連接的方法。

表示層:處理用戶信息的表示問題,如編碼、數(shù)據(jù)格式轉(zhuǎn)換和加密解密等。

應(yīng)用層:直接向用戶提供服務(wù),完成用戶希望在網(wǎng)絡(luò)上完成的各種工作。

85.get和post請求有哪些區(qū)別?

get請求會被瀏覽器主動緩存,而post不會。

get傳遞參數(shù)有大小限制,而post沒有。

post參數(shù)傳輸更安全,get的參數(shù)會明文限制在url上,post不會。

86.如何實現(xiàn)跨域?

實現(xiàn)跨域有以下幾種方案:服務(wù)器端運(yùn)行跨域設(shè)置CORS等于*;

在單個接口使用注解@CrossOrigin運(yùn)行跨域;

使用jsonp跨域;

87.說一下JSONP實現(xiàn)原理?

jsonp:JSONwithPadding,它是利用script標(biāo)簽的src連接可以訪問不同源的特性,加載遠(yuǎn)程返回的“JS函數(shù)”來執(zhí)行的。設(shè)計模式

88.說一下你熟悉的設(shè)計模式?

單例模式:保證被創(chuàng)建一次,節(jié)省系統(tǒng)開銷。

工廠模式(簡單工廠、抽象工廠):解耦代碼。

觀察者模式:定義了對象之間的一對多的依賴,這樣一來,當(dāng)一個對象改變時,它的所有的依賴者都會收到通知并自動更新。

外觀模式:提供一個統(tǒng)一的接口,用來訪問子系統(tǒng)中的一群接口,外觀定義了一個高層的接口,讓子系統(tǒng)更容易使用。

模版方法模式:定義了一個算法的骨架,而將一些步驟延遲到子類中,模版方法使得子類可以在不改變算法結(jié)構(gòu)的情況下,重新定義算法的步驟。

狀態(tài)模式:允許對象在內(nèi)部狀態(tài)改變時改變它的行為,對象看起來好像修改了它的類。

89.簡單工廠和抽象工廠有什么區(qū)別?

簡單工廠:用來生產(chǎn)同一等級結(jié)構(gòu)中的任意產(chǎn)品,對于增加新的產(chǎn)品,無能為力。

工廠方法:用來生產(chǎn)同一等級結(jié)構(gòu)中的固定產(chǎn)品,支持增加任意產(chǎn)品。

抽象工廠:用來生產(chǎn)不同產(chǎn)品族的全部產(chǎn)品,對于增加新的產(chǎn)品,無能為力;支持增加產(chǎn)品族。

Spring/SpringMVC

90.為什么要使用spring?

spring提供ioc技術(shù),容器會幫你管理依賴的對象,從而不需要自己創(chuàng)建和管理依賴對象了,更輕松的實現(xiàn)了程序的解耦。

spring提供了事務(wù)支持,使得事務(wù)操作變的更加方便。

spring提供了面向切片編程,這樣可以更方便的處理某一類的問題。

更方便的框架集成,spring可以很方便的集成其他框架,比如MyBatis、hibernate等。

91.解釋一下什么是aop?

aop是面向切面編程,通過預(yù)編譯方式和運(yùn)行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。簡單來說就是統(tǒng)一處理某一“切面”(類)的問題的編程思想,比如統(tǒng)一處理日志、異常等。解釋一下什么是ioc?

ioc:InversionofControl(中文:控制反轉(zhuǎn))是spring的核心,對于spring框架來說,就是由spring來負(fù)責(zé)控制對象的生命周期和對象間的關(guān)系。簡單來說,控制指的是當(dāng)前對象對內(nèi)部成員的控制權(quán);控制反轉(zhuǎn)指的是,這種控制權(quán)不由當(dāng)前對象管理了,由其他(類,第三方容器)來管理。spring有哪些主要模塊?

springcore:框架的最基礎(chǔ)部分,提供ioc和依賴注入特性。

springcontext:構(gòu)建于core封裝包基礎(chǔ)上的context封裝包,提供了一種框架式的對象訪問方法。

springdao:DataAccessObject提供了JDBC的抽象層。

springaop:提供了面向切面的編程實現(xiàn),讓你可以自定義攔截器、切點等。

springWeb:提供了針對Web開發(fā)的集成特性,例如文件上傳,利用servletlisteners進(jìn)行ioc容器初始化和針對Web的ApplicationContext。

springWebmvc:spring中的mvc封裝包提供了Web應(yīng)用的Model-View-Controller(MVC)的實現(xiàn)。spring常用的注入方式有哪些?

setter屬性注入

構(gòu)造方法注入

注解方式注入spring中的bean是線程安全的嗎?

spring中的bean默認(rèn)是單例模式,spring框架并沒有對單例bean進(jìn)行多線程的封裝處理。實際上大部分時候springbean無狀態(tài)的(比如dao類),所有某種程度上來說bean也是安全的,但如果bean有狀態(tài)的話(比如viewmodel對象),那就要開發(fā)者自己去保證線程安全了,最簡單的就是改變bean的作用域,把“singleton”變更為“prototype”,這樣請求bean相當(dāng)于newBean()了,所以就可以保證線程安全了。有狀態(tài)就是有數(shù)據(jù)存儲功能。

無狀態(tài)就是不會保存數(shù)據(jù)。

96.spring支持幾種bean的作用域?

spring支持5種作用域,如下:singleton:springioc容器中只存在一個bean實例,bean以單例模式存在,是系統(tǒng)默認(rèn)值;

prototype:每次從容器調(diào)用bean時都會創(chuàng)建一個新的示例,既每次getBean()相當(dāng)于執(zhí)行newBean()操作;

Web環(huán)境下的作用域:

request:每次http請求都會創(chuàng)建一個bean;

session:同一個httpsession共享一個bean實例;

global-session:用于portlet容器,因為每個portlet有單獨(dú)的session,globalsession提供一個全局性的httpsession。

注意:使用prototype作用域需要慎重的思考,因為頻繁創(chuàng)建和銷毀bean會帶來很大的性能開銷。spring自動裝配bean有哪些方式?

no:默認(rèn)值,表示沒有自動裝配,應(yīng)使用顯式bean引用進(jìn)行裝配。

byName:它根據(jù)bean的名稱注入對象依賴項。

byType:它根據(jù)類型注入對象依賴項。

構(gòu)造函數(shù):通過構(gòu)造函數(shù)來注入依賴項,需要設(shè)置大量的參數(shù)。

autodetect:容器首先通過構(gòu)造函數(shù)使用autowire裝配,如果不能,則通過byType自動裝配。spring事務(wù)實現(xiàn)方式有哪些?

聲明式事務(wù):聲明式事務(wù)也有兩種實現(xiàn)方式,基于xml配置文件的方式和注解方式(在類上添加@Transaction注解)。

編碼方式:提供編碼的形式管理和維護(hù)事務(wù)。說一下spring的事務(wù)隔離?

spring有五大隔離級別,默認(rèn)值為ISOLATION_DEFAULT(使用數(shù)據(jù)庫的設(shè)置),其他四個隔離級別和數(shù)據(jù)庫的隔離級別一致:ISOLATION_DEFAULT:用底層數(shù)據(jù)庫的設(shè)置隔離級別,數(shù)據(jù)庫設(shè)置的是什么我就用什么;ISOLATIONREADUNCOMMITTED:未提交讀,最低隔離級別、事務(wù)未提交前,就可被其他事務(wù)讀?。〞霈F(xiàn)幻讀、臟讀、不可重復(fù)讀);ISOLATIONREADCOMMITTED:提交讀,一個事務(wù)提交后才能被其他事務(wù)讀取到(會造成幻讀、不可重復(fù)讀),SQLserver的默認(rèn)級別;ISOLATIONREPEATABLEREAD:可重復(fù)讀,保證多次讀取同一個數(shù)據(jù)時,其值都和事務(wù)開始時候的內(nèi)容是一致,禁止讀取到別的事務(wù)未提交的數(shù)據(jù)(會造成幻讀),MySQL的默認(rèn)級別;ISOLATION_SERIALIZABLE:序列化,代價最高最可靠的隔離級別,該隔離級別能防止臟讀、不可重復(fù)讀、幻讀。臟讀:表示一個事務(wù)能夠讀取另一個事務(wù)中還未提交的數(shù)據(jù)。比如,某個事務(wù)嘗試插入記錄A,此時該事務(wù)還未提交,然后另一個事務(wù)嘗試讀取到了記錄A。不可重復(fù)讀:是指在一個事務(wù)內(nèi),多次讀同一數(shù)據(jù)?;米x:指同一個事務(wù)內(nèi)多次查詢返回的結(jié)果集不一樣。比如同一個事務(wù)A第一次查詢時候有n條記錄,但是第二次同等條件下查詢卻有n+1條記錄,這就好像產(chǎn)生了幻覺。發(fā)生幻讀的原因也是另外一個事務(wù)新增或者刪除或者修改了第一個事務(wù)結(jié)果集里面的數(shù)據(jù),同一個記錄的數(shù)據(jù)內(nèi)容被修改了,所有數(shù)據(jù)行的記錄就變多或者變少了。說一下springmvc運(yùn)行流程?

springmvc先將請求發(fā)送給DispatcherServlet。

DispatcherServlet查詢一個或多個HandlerMapping,找到處理請求的Controller。

DispatcherServlet再把請求提交到對應(yīng)的Controller。

Controller進(jìn)行業(yè)務(wù)邏輯處理后,會返回一個ModelAndView。

Dispathcher查詢一個或多個ViewResolver視圖解析器,找到ModelAndView對象指定的視圖對象。

視圖對象負(fù)責(zé)渲染返回給客戶端。springmvc有哪些組件?

前置控制器DispatcherServlet。

映射控制器HandlerMapping。

處理器Controller。

模型和視圖ModelAndView。

視圖解析器ViewResolver。@RequestMapping的作用是什么?

將http請求映射到相應(yīng)的類/方法上。@Autowired的作用是什么?

@Autowired它可以對類成員變量、方法及構(gòu)造函數(shù)進(jìn)行標(biāo)注,完成自動裝配的工作,通過@Autowired的使用來消除set/get方法。SpringBoot/SpringCloud

104.什么是springboot?

springboot是為spring服務(wù)的,是用來簡化新spring應(yīng)用的初始搭建以及開發(fā)過程的。為什么要用springboot?

配置簡單

獨(dú)立運(yùn)行

自動裝配

無代碼生成和xml配置

提供應(yīng)用監(jiān)控

易上手

提升開發(fā)效率springboot核心配置文件是什么?

springboot核心的兩個配置文件:bootstrap(.yml或者.properties):boostrap由父ApplicationContext加載的,比applicaton優(yōu)先加載,且boostrap里面的屬性不能被覆蓋;

application(.yml或者.properties):用于springboot項目的自動化配置。

107.springboot配置文件有哪幾種類型?它們有什么區(qū)別?

配置文件有.properties格式和.yml格式,它們主要的區(qū)別是書法風(fēng)格不同。.properties配置如下:spring.RabbitMQ.port=5672

.yml配置如下:spring:

RabbitMQ:

port:5672

.yml格式不支持@PropertySource注解導(dǎo)入。springboot有哪些方式可以實現(xiàn)熱部署?

使用devtools啟動熱部署,添加devtools庫,在配置文件中把spring.devtools.restart.enabled設(shè)置為true;

使用IntellijIdea編輯器,溝上自動編譯或手動重新編譯。jpa和hibernate有什么區(qū)別?

jpa全稱JavaPersistenceAPI,是Java持久化接口規(guī)范,hibernate屬于jpa的具體實現(xiàn)。什么是springcloud?

springcloud是一系列框架的有序集合。它利用springboot的開發(fā)便利性巧妙地簡化了分布式系統(tǒng)基礎(chǔ)設(shè)施的開發(fā),如服務(wù)發(fā)現(xiàn)注冊、配置中心、消息總線、負(fù)載均衡、斷路器、數(shù)據(jù)監(jiān)控等,都可以用springboot的開發(fā)風(fēng)格做到一鍵啟動和部署。springcloud斷路器的作用是什么?

在分布式架構(gòu)中,斷路器模式的作用也是類似的,當(dāng)某個服務(wù)單元發(fā)生故障(類似用電器發(fā)生短路)之后,通過斷路器的故障監(jiān)控(類似熔斷保險絲),向調(diào)用方返回一個錯誤響應(yīng),而不是長時間的等待。這樣就不會使得線程因調(diào)用故障服務(wù)被長時間占用不釋放,避免了故障在分布式系統(tǒng)中的蔓延。springcloud的核心組件有哪些?

Eureka:服務(wù)注冊于發(fā)現(xiàn)。

Feign:基于動態(tài)代理機(jī)制,根據(jù)注解和選擇的機(jī)器,拼接請求url地址,發(fā)起請求。

Ribbon:實現(xiàn)負(fù)載均衡,從一個服務(wù)的多臺機(jī)器中選擇一臺。

Hystrix:提供線程池,不同的服務(wù)走不同的線程池,實現(xiàn)了不同服務(wù)調(diào)用的隔離,避免了服務(wù)雪崩的問題。

Zuul:網(wǎng)關(guān)管理,由Zuul網(wǎng)關(guān)轉(zhuǎn)發(fā)請求給對應(yīng)的服務(wù)。

Hibernate為什么要使用hibernate?

hibernate是對jdbc的封裝,大大簡化了數(shù)據(jù)訪問層的繁瑣的重復(fù)性代碼。

hibernate是一個優(yōu)秀的ORM實現(xiàn),很多程度上簡化了DAO層的編碼功能。

可以很方便的進(jìn)行數(shù)據(jù)庫的移植工作。

提供了緩存機(jī)制,是程序執(zhí)行更改的高效。什么是ORM框架?

ORM(ObjectRelationMapping)對象關(guān)系映射,是把數(shù)據(jù)庫中的關(guān)系數(shù)據(jù)映射成為程序中的對象。使用ORM的優(yōu)點:提高了開發(fā)效率降低了開發(fā)成本、開發(fā)更簡單更對象化、可移植更強(qiáng)。hibernate中如何在控制臺查看打印的SQL語句?

在Config里面把hibernate.show_SQL設(shè)置為true就可以。但不建議開啟,開啟之后會降低程序的運(yùn)行效率。hibernate有幾種查詢方式?

三種:hql、原生SQL、條件查詢Criteria。hibernate實體類可以被定義為final嗎?

實體類可以定義為final類,但這樣的話就不能使用hibernate代理模式下的延遲關(guān)聯(lián)提供性能了,所以不建議定義實體類為final。在hibernate中使用Integer和int做映射有什么區(qū)別?

Integer類型為對象,它的值允許為null,而int屬于基礎(chǔ)數(shù)據(jù)類型,值不能為null。hibernate是如何工作的?

讀取并解析配置文件。

讀取并解析映射文件,創(chuàng)建SessionFactory。

打開Session。

創(chuàng)建事務(wù)。

進(jìn)行持久化操作。

提交事務(wù)。

關(guān)閉Session。

關(guān)閉SessionFactory。get()和load()的區(qū)別?

數(shù)據(jù)查詢時,沒有OID指定的對象,get()返回null;load()返回一個代理對象。

load()支持延遲加載;get()不支持延遲加載。說一下hibernate的緩存機(jī)制?

hibernate常用的緩存有一級緩存和二級緩存:一級緩存:也叫Session緩存,只在Session作用范圍內(nèi)有效,不需要用戶干涉,由hibernate自身維護(hù),可以通過:evict(object)清除object的緩存;clear()清除一級緩存中的所有緩存;flush()刷出緩存;二級緩存:應(yīng)用級別的緩存,在所有Session中都有效,支持配置第三方的緩存,如:EhCache。hibernate對象有哪些狀態(tài)?

臨時/瞬時狀態(tài):直接new出來的對象,該對象還沒被持久化(沒保存在數(shù)據(jù)庫中),不受Session管理。

持久化狀態(tài):當(dāng)調(diào)用Session的save/saveOrupdate/get/load/list等方法的時候,對象就是持久化狀態(tài)。

游離狀態(tài):Session關(guān)閉之后對象就是游離狀態(tài)。在hibernate中g(shù)etCurrentSession和openSession的區(qū)別是什么?

getCurrentSession會綁定當(dāng)前線程,而openSession則不會。

getCurrentSession事務(wù)是Spring控制的,并且不需要手動關(guān)閉,而openSession需要我們自己手動開啟和提交事務(wù)。hibernate實體類必須要有無參構(gòu)造函數(shù)嗎?為什么?

hibernate中每個實體類必須提供一個無參構(gòu)造函數(shù),因為hibernate框架要使用reflectionapi,通過調(diào)用ClassnewInstance()來創(chuàng)建實體類的實例,如果沒有無參的構(gòu)造函數(shù)就會拋出異常。MyBatis

125.MyBatis中#{}和

的區(qū)別是什么?#是預(yù)編譯處理,{}的區(qū)別是什么?\#{}是預(yù)編譯處理,的區(qū)別是什么?#是預(yù)編譯處理,{}是字符替換。在使用#{}時,MyBatis會將SQL中的#{}替換成“?”,配合PreparedStatement的set方法賦值,這樣可以有效的防止SQL注入,保證程序的運(yùn)行安全。MyBatis有幾種分頁方式?

分頁方式:邏輯分頁和物理分頁。邏輯分頁:使用MyBatis自帶的RowBounds進(jìn)行分頁,它是一次性查詢很多數(shù)據(jù),然后在數(shù)據(jù)中再進(jìn)行檢索。物理分頁:自己手寫SQL分頁或使用分頁插件PageHelper,去數(shù)據(jù)庫查詢指定條數(shù)的分頁數(shù)據(jù)的形式。RowBounds是一次性查詢?nèi)拷Y(jié)果嗎?為什么?

RowBounds表面是在“所有”數(shù)據(jù)中檢索數(shù)據(jù),其實并非是一次性查詢出所有數(shù)據(jù),因為MyBatis是對jdbc的封裝,在jdbc驅(qū)動中有一個FetchSize的配置,它規(guī)定了每次最多從數(shù)據(jù)庫查詢多少條數(shù)據(jù),假如你要查詢更的數(shù)據(jù),它會在你執(zhí)行next()的時候,去查詢更多的數(shù)據(jù)。就好比你去自動取款機(jī)取10000元,但取款機(jī)每次最多能取2500元,所以你要取4次才能把錢取完。只是對于jdbc來說,當(dāng)你調(diào)用next()的時候會自動幫你完成查詢工作。這樣做的好處可以有效的防止內(nèi)存溢出。FetchSize官方相關(guān)文檔:http://t.cn/EfSE2g3MyBatis邏輯分頁和物理分頁的區(qū)別是什么?

邏輯分頁是一次性查詢很多數(shù)據(jù),然后再在結(jié)果中檢索分頁的數(shù)據(jù)。這樣做弊端是需要消耗大量的內(nèi)存、有內(nèi)存溢出的風(fēng)險、對數(shù)據(jù)庫壓力較大。

物理分頁是從數(shù)據(jù)庫查詢指定條數(shù)的數(shù)據(jù),彌補(bǔ)了一次性全部查出的所有數(shù)據(jù)的種種缺點,比如需要大量的內(nèi)存,對數(shù)據(jù)庫查詢壓力較大等問題。MyBatis是否支持延遲加載?延遲加載的原理是什么?

MyBatis支持延遲加載,設(shè)置lazyLoadingEnabled=true即可。延遲加載的原理的是調(diào)用的時候觸發(fā)加載,而不是在初始化的時候就加載信息。比如調(diào)用a.getB().getName(),這個時候發(fā)現(xiàn)a.getB()的值為null,此時會單獨(dú)觸發(fā)事先保存好的關(guān)聯(lián)B對象的SQL,先查詢出來B,然后再調(diào)用a.setB(b),而這時候再調(diào)用a.getB().getName()就有值了,這就是延遲加載的基本原理。說一下MyBatis的一級緩存和二級緩存?

一級緩存:基于PerpetualCache的HashMap本地緩存,它的聲明周期是和SQLSession一致的,有多個SQLSession或者分布式的環(huán)境中數(shù)據(jù)庫操作,可能會出現(xiàn)臟數(shù)據(jù)。當(dāng)Sessionflush或close之后,該Session中的所有Cache就將清空,默認(rèn)一級緩存是開啟的。

二級緩存:也是基于PerpetualCache的HashMap本地緩存,不同在于其存儲作用域為Mapper級別的,如果多個SQLSession之間需要共享緩存,則需要使用到二級緩存,并且二級緩存可自定義存儲源,如Ehcache。默認(rèn)不打開二級緩存,要開啟二級緩存,使用二級緩存屬性類需要實現(xiàn)Serializable序列化接口(可用來保存對象的狀態(tài))。

開啟二級緩存數(shù)據(jù)查詢流程:二級緩存->一級緩存->數(shù)據(jù)庫。緩存更新機(jī)制:當(dāng)某一個作用域(一級緩存Session/二級緩存Mapper)進(jìn)行了C/U/D操作后,默認(rèn)該作用域下所有select中的緩存將被clear。MyBatis和hibernate的區(qū)別有哪些?

靈活性:MyBatis更加靈活,自己可以寫SQL語句,使用起來比較方便。

可移植性:MyBatis有很多自己寫的SQL,因為每個數(shù)據(jù)庫的SQL可以不相同,所以可移植性比較差。

學(xué)習(xí)和使用門檻:MyBatis入門比較簡單,使用門檻也更低。

二級緩存:hibernate擁有更好的二級緩存,

溫馨提示

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

評論

0/150

提交評論