Java面試大全(2020年版)1-100

目錄

1. ArrayList和LinkedList的區別是什麼(面試)?

  • 是否保證線程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保證線程安全;
  • 底層數據結構: Arraylist 底層使用的是Object數組;LinkedList 底層使用的是雙向循環鏈表數據結構;
  • 插入和刪除是否受元素位置的影響: ① ArrayList 採用數組存儲,所以插入和刪除元素的時間複雜度受元素位置的影響。 比如:執行add(E e)方法的時候, ArrayList 會默認在將指定的元素追加到此列表的末尾,這種情況時間複雜度就是O(1)。但是如果要在指定位置 i 插入和刪除元素的話(add(int index, E element))時間複雜度就爲 O(n-i)。因爲在進行上述操作的時候集合中第 i 和第 i 個元素之後的(n-i)個元素都要執行向後位/向前移一位的操作。 ② LinkedList 採用鏈表存儲,所以插入,刪除元素時間複雜度不受元素位置的影響,都是近似 O(1)而數組爲近似 O(n)。
  • 是否支持快速隨機訪問: LinkedList 不支持高效的隨機元素訪問,而ArrayList 實現了RandmoAccess 接口,所以有隨機訪問功能。快速隨機訪問就是通過元素的序號快速獲取元素對象(對應於get(int index)方法)。
  • 內存空間佔用: ArrayList的空 間浪費主要體現在在list列表的結尾會預留一定的容量空間,而LinkedList的空間花費則體現在它的每一個元素都需要消耗比ArrayList更多的空間(因爲要存放直接後繼和直接前驅以及數據)。

2. 什麼是List接口

  • 是元素有序並且可以重複的集合,被稱爲序列,
  • List可以精準的控制每個元素的插入位置,或者刪除某個位置元素
  • List接口的常用子類有ArrayList,LinkedList,Vector(已經過時)

3. 什麼是HashMap(重點)

  • HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key
  • 本質爲無序散列,Hash算法來決定存儲位置.
  • HashMap的數據結構和底層實現(面試重點),JDk1.8之前的HashMap由數組+鏈表組成的,即”鏈表散列”,數組是HashMap的主題,鏈表則是主要是爲了解決哈希衝突而存在的(“拉鍊法”),如果定位到的數組位置不含鏈表(entry的next指向null),那麼對於查找,添加等操作很快,僅需要一次就能尋找到地址;如果定位到數組包含鏈表,對於添加操作,其時間複雜度依然爲O(1),因爲最新的Entry會插入鏈表頭部,急需要簡單改變引用鏈即可,而對於查找操作來講,此時就需要遍歷鏈表,然後通過key對象的equals方法逐一對比.
  • HashMap不是線程安全的,當迭代其中有其他的線程改變了HashMap中的值將會拋出ConcurrentModifcationException.

4. 關於HashMap的擴容機制

Threshold(開始擴容的臨界點)=Size(HashMap的容量)*Load_Factor(負載因子);

5. 什麼時候開始擴容?

當HashMap中的元素個數超過數組大小(數組總大小length,不是數組中個數size)loadFactor時,就會進行數組擴容,loadFactor的默認值爲0.75,這是一個折中的取值。也就是說,默認情況下,數組大小爲16,那麼當HashMap中元素個數超過160.75=12(這個值就是代碼中的threshold值,也叫做臨界值)的時候,就把數組的大小擴展爲 2*16=32,即擴大一倍,然後重新計算每個元素在數組中的位置。
爲什麼是0.75,大量實驗得出的結果
如果取0.5,超過一般就擴容,造成資源的浪費.
如果取1,到臨界值才擴容,會增加哈希碰撞的機率.

6. 擴容的方法是?

調用resize方法

7. Hashmap爲什麼大小是2的冪次?

爲了能讓 HashMap 存取高效,儘量較少碰撞,也就是要儘量把數據分配均勻,每個鏈表/紅黑樹長度大致相同。這個實現就是把數據存到哪個鏈表/紅黑樹中的算法。

8. HashMap線程安全問題,對應的線程安全Map是什麼?

  • 對應的的是ConCurrentHashMap支持高併發的訪問和更新,它是線程安全的.
  • ConCurrentHashMap在JDK1.8中和HashMap的底層相同都是散列表+紅黑樹
  • 通過部分鎖定+CAs算法來進行實現線程安全的.
  • ConCurrentHashMap的key和Value都不能爲null。

9. 什麼是CAs算法?

Compare and swap是一種有名的無鎖算法,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其他線程都失敗,失敗的線程並不會被掛起,而是被告知這次競爭中失敗,並可以再次嘗試.
總結:先比較是否相等,如果相當則替換。

10. 什麼是進程?

是指一個內存中運行的應用程序,每個進程都有一個獨立的內存空間,一個應用程序可以同時運行多個進程;進程也是程序的一次執行過程,是系統運行程序的基本單位;系統運行一個程序即是一個進程從創建、運行到消亡的過程。

11. 什麼是線程?

進程內部的一個獨立執行單元;一個進程可以同時併發的運行多個線程,可以理解爲一個進程便相當於一個單 CPU 操作系統,而線程便是這個系統中運行的多個任務。

12. 什麼是併發?

指在同一時刻只能有一條指令執行,但多個進程指令被快速輪換執行,使得在宏觀上有多個進程同時執行的效果。

13. 什麼是並行?

指在同一時刻,有多條指令在多個處理器上同時執行。

14. 多線程有什麼優勢?

  • 進程之間不能共享內存,但線程之間共享內存非常容易。
  • 系統創建進程時需要爲該進程重新分配系統資源,但創建線程則代價小得多,因此使用多線程來實現多任務併發比多進程的效率高
  • Java語言內置了多線程功能支持,從而簡化了Java的多線程編程

15. Thread和Runnable的區別

實現Runnable接口比繼承Thread類所具有的優勢:

  • 適合多個相同的程序代碼的線程去處理同一個資源
  • 可以避免java中的單繼承的限制
  • 增加程序的健壯性,代碼可以被多個線程共享,代碼和數據獨立
  • 線程池只能放入實現Runable或callable類線程,不能直接放入繼承Thread的類

16. 多線程的生命週期

在線程的生命週期中,它要經過新建(New)、就緒(Runnable)、運行(Running)、阻塞(Blocked)和死亡(Dead)五種狀態。
流程:
1)、新建狀態(New):新創建了一個線程對象。
2)、就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
3)、運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
4)、阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的情況分三種:
(一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。(wait會釋放持有的鎖)
(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。
(三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。(注意,sleep是不會釋放持有的鎖)
5)、死亡狀態(Dead):線程會以一下三種方式結束:
①run()或call()方法執行完成,線程正常結束
②線程拋出一個未捕獲的Exception或Error
③直接調用該線程的stop()方法來結束線程——該方法容易導致死鎖
注:當主線程結束時,其他線程不受影響,不會隨之結束。
線程睡眠:Thread.sleep(long millis)方法,使線程轉到阻塞狀態。millis參數設定睡眠的時間,以毫秒爲單位。當睡眠結束後,就轉爲就緒(Runnable)狀態。sleep()平臺移植性好。
線程等待:Object類中的wait()方法(無限等待),導致當前的線程等待,直到其他線程調用此對象的 notify() 方法或 notifyAll() 喚醒方法。這個兩個喚醒方法也是Object類中的方法,行爲等價於調用 wait(0) 一樣。
線程讓步:Thread.yield() 方法,暫停當前正在執行的線程對象,把執行機會讓給相同或者更高優先級的線程。
線程加入:join()方法,等待其他線程終止。在當前線程中調用另一個線程的join()方法,則當前線程轉入阻塞狀態,直到另一個進程運行結束,當前線程再由阻塞轉爲就緒狀態。
線程喚醒:Object類中的notify()方法,喚醒在此對象監視器上等待的單個線程。如果所有線程都在此對象上等待,則會選擇喚醒其中一個線程。選擇是任意性的,並在對實現做出決定時發生。線程通過調用其中一個 wait 方法,在對象的監視器上等待。 直到當前的線程放棄此對象上的鎖定,才能繼續執行被喚醒的線程。被喚醒的線程將以常規方式與在該對象上主動同步的其他所有線程進行競爭;例如,喚醒的線程在作爲鎖定此對象的下一個線程方面沒有可靠的特權或劣勢。類似的方法還有一個notifyAll(),喚醒在此對象監視器上等待的所有線程。

17. 什麼是線程安全和線程不安全?

由於系統的線程調度具有一定的隨機性,當使用多個線程來訪問同一個數據時,很容易“偶然“出現線程安全問題。
線程安全問題都是由全局變量及靜態變量引起的。若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。

18. 什麼叫線程安全?

就是多線程訪問時,採用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問,直到該線程讀取完,其他線程纔可使用。不會出現數據不一致或者數據污染。
一個線程安全的計數器類的同一個實例對象在被多個線程使用的情況下也不會出現計算失誤。很顯然你可以將集合類分成兩組,線程安全和非線程安全的。Vector 是用同步方法來實現線程安全的, 而和它相似的ArrayList不是線程安全的。

19. 何爲線程不安全

線程不安全:就是不提供數據訪問保護,有可能出現多個線程先後更改數據造成所得到的數據是髒數據
如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。
線程安全問題都是由全局變量及靜態變量引起的。若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。

20. 線程同步鎖有什麼特點?

同步代碼塊:synchronized 關鍵字可以用於方法中的某個區塊中,表示只對這個區塊的資源實行互斥訪問。
synchronized(obj){需要同步的代碼(多條語句操作共享數據的代碼)}
obj:同步鎖:
對象的同步鎖只是一個概念,可以想象爲在對象上標記了一個鎖.

  1. 鎖對象可以是任意類型。
  2. 多個線程對象要使用同一把鎖。

21. 同步有什麼特點:

同步的前提是:多個線程並且多個線程使用的是同一個鎖對象

22. 同步的有什麼好處

同步的出現解決了多線程的安全問題

23. 同步有什麼弊端

當線程相當多時,因爲每個線程都會去判斷同步上的鎖,這是很耗費資源的,無形中會降低程序的運行效率

24. 同步方法:

同步方法就是使用synchronized關鍵字來修飾某個方法,則該方法稱爲同步方法。同步方法的同步監視器是this,也就是調用該方法的對象。

25. 同步鎖是誰?

對於非static方法,同步鎖就是this。
對於static方法,我們使用當前方法所在類的字節碼對象(類名.class)。

26. 線程安全的類具有什麼特徵

  • 該類的對象可以被多個線程安全的訪問
  • 每個線程調用該對象的任意方法之後都將得到正確結果
  • 每個線程調用該對象的任意方法之後,該對象狀態依然保持合理狀態。

27. Java中sleep方法和wait方法的區別?

雖然兩者都是用來暫停當前運行的線程,但是 sleep() 實際上只是短暫停頓,因爲它不會釋放鎖,而 wait() 意味着條件等待,這就是爲什麼該方法要釋放鎖,因爲只有這樣,其他等待的線程才能在滿足條件時獲取到該鎖

28. run()方法和start()方法區別:

run()方法是多線程程序的一個約定。所有的多線程代碼都在run方法裏面。啓動線程使用start()方法,不是run()方法。調用start()方法來啓動線程,系統會把該線程run()方法當成線程執行體來處理。如果直接調用run()方法,則run()方法會被當成普通方法立即執行,而不是線程執行體。而且在run()方法返回之前其他線程無法併發執行。

29. 多線程有幾種實現方法?同步有幾種實現方法?

①多線程有兩種實現方法,分別是繼承Thread類與實現Runnable接口
②同步的實現方面有兩種,分別是synchronized,wait與notify
wait():使一個線程處於等待狀態,並且釋放所持有的對象的lock。
sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要捕捉
InterruptedException異常。
notify():喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,並不能確切的喚醒某
一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先級。
Allnotity():喚醒所有處入等待狀態的線程,注意並不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。

30. 啓動一個線程是用run()還是start()?

啓動一個線程是調用start()方法,使線程就緒狀態,以後可以被調度爲運行狀態,一個線程必須關聯一些具體的執行代碼,run()方法是該線程所關聯的執行代碼。

31. 當一個線程進入一個對象的一個synchronized方法後,其它線程是否可進入此對象的其它方法?

分幾種情況
1).其他方法前是否加了synchronized關鍵字,如果沒加,則能。
2).如果這個方法內部調用了wait,則可以進入其他synchronized方法。
3).如果其他個方法都加了synchronized關鍵字,並且內部沒有調用wait,則不能。
4).如果其他方法是static,它用的同步鎖是當前類的字節碼,與非靜態的方法不能同步,因爲非靜態的方法用的是this。

32. 線程的基本概念、線程的基本狀態以及狀態之間的關係

①一個程序中可以有多條執行線索同時執行,一個線程就是程序中的一條執行線索,每個線程上都關聯有要執行的代碼,即可以有多段程序代碼同時運行,每個程序至少都有一個線程,即main方法執行的那個線程。(如果只是一個cpu,它怎麼能夠同時執行多段程序呢?這是從宏觀上來看的,cpu一會執行a線索,一會執行b線索,切換時間很快,給人的感覺是a,b在同時執行,好比大家在同一個辦公室上網,只有一條鏈接到外部網線,其實,這條網線一會爲a傳數據,一會爲b傳數據,由於切換時間很短暫,所以,大家感覺都在同時上網。)
②線程基本狀態:就緒,運行,synchronize阻塞,wait和sleep掛起,結束。wait必須在synchronized內部調用。調用線程的start方法後線程進入就緒狀態,線程調度系統將就緒狀態的線程轉爲運行狀態,遇到synchronized語句時,由運行狀態轉爲阻塞,當synchronized獲得鎖後,由阻塞轉爲運行,在這種情況可以調用wait方法轉爲掛起狀態,當線程關聯的代碼執行完後,線程變爲結束狀態。

33. 簡述synchronized和java.util.concurrent.locks.Lock的異同?

主要相同點:Lock能完成synchronized所實現的所有功能
主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,並且必須在finally從句中釋放。Lock還有更強大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。

34. java中有幾種類型的流?

字符流和字節流。字節流繼承inputStream和OutputStream,字符流繼承自InputSteamReader和OutputStreamWriter。

35. 談談Java IO裏面的常見類,字節流,字符流、接口、實現類、方法阻塞

輸入流就是從外部文件輸入到內存,輸出流主要是從內存輸出到文件。
IO流主要分爲字符流和字節流。
①字符流中有抽象類InputStream和OutputStream,它們的子類FileInputStream,FileOutputStream,BufferedOutputStream等。
②字符流BufferedReader和Writer等。都實現了Closeable, Flushable,
③Appendable這些接口。程序中的輸入輸出都是以流的形式保存的,流中保存的實際上全都是字節文件。
④java中的阻塞式方法是指在程序調用改方法時,必須等待輸入數據可用或者檢測到輸入結束或者拋出異常,否則程序會一直停留在該語句上,不會執行下面的語句。比如read()和readLine()方法。

36. 字符流和字節流有什麼區別?

字符流以字符或者字符數組的形式讀寫數據,只能讀寫二進制文件;字節流能讀寫各種類型的數據。
字節流與字符流的不同是他們的處理方式,字節流是最基本的,採用ASCII編碼。
但是實際上很多數據是文本,所以提出字符流的概念,採用unicode編碼
兩者之間通過inputStreamReader與outputStreamWriter來關聯,實際上是通過byte[]與String來關聯
字節流輸出: 程序–>字節流–>文件
字符流輸出:程序–>字符流–>緩衝–>文件
程序中所有的數據都是以流的方式進行傳輸與保存的
在關閉字符流後會強制性的將緩衝區的數據輸出,若沒有關閉緩衝區的內容是無法輸出的,
如果想不關閉並且還想輸出緩衝區的內容,用writer類的flush()方法來完成,

37. 講講NIO

看了一些文章,傳統的IO流是阻塞式的,會一直監聽一個ServerSocket,在調用read等方法時,他會一直等到數據到來或者緩衝區已滿時才返回。調用accept也是一直阻塞到有客戶端連接纔會返回。每個客戶端連接過來後,服務端都會啓動一個線程去處理該客戶端的請求。並且多線程處理多個連接。每個線程擁有自己的棧空間並且佔用一些 CPU 時間。每個線程遇到外部未準備好的時候,都會阻塞掉。阻塞的結果就是會帶來大量的進程上下文切換。
對於NIO,它是非阻塞式,核心類:
1.Buffer爲所有的原始類型提供 (Buffer)緩存支持。
2.Charset字符集編碼解碼解決方案
3.Channel一個新的原始I/O抽象,用於讀寫Buffer類型,通道可以認爲是一種連接,可以是到特定設備,程序或者是網絡的連接。

38. BufferedReader屬於哪種流,它主要是用來做什麼的,它裏面有那些經典的方法

屬於處理流中的緩衝流,可以將讀取的內容存在內存裏面,有readLine()方法

39. 什麼是節點流,什麼是處理流,它們各有什麼用處,處理流的創建有什麼特徵

節點流直接與數據源相連,用於輸入或者輸出處理流:在節點流的基礎上對之進行加工,進行一些功能的擴展處理流的構造器必須要 傳入節點流的子類

40. 如果我要對字節流進行大量的從硬盤讀取,要用那個流,爲什麼

BufferedInputStream使用緩衝流能夠減少對硬盤的損傷

41. 如果我要打印出不同類型的數據到數據源,那麼最適合的流是那個流,爲什麼

Printwriter可以打印各種數據類型

42. 怎麼樣把我們控制檯的輸出改成輸出到一個文件裏面,這個技術叫什麼

SetOut(printWriter,printStream)重定向

43. 怎麼樣把輸出字節流轉換成輸出字符流,說出它的步驟

使用轉換處理流OutputStreamWriter 可以將字節流轉爲字符流New OutputStreamWriter(new FileOutputStream(File file));

44. 什麼叫對象序列化,什麼是反序列化,實現對象序列化需要做哪些工作

對象序列化:將對象以二進制的形式保存到硬盤上;
反序列化:將二進制文件轉化爲對象讀取.
將需要序化的類實現Serializable接口

45. 解釋一下java.io.Serializable接口

類通過實現 Java.io.Serializable 接口以啓用其序列化功能。未實現此接口的類將無法使其任何狀態序列化或反序列化。
①PrintStream、BufferedWriter、PrintWriter的比較?
PrintStream類的輸出功能非常強大,通常如果需要輸出文本內容,都應該將輸出流包裝成PrintStream後進行輸出。
②與其他輸出流不同,PrintStream 永遠不會拋出 IOException;而是,異常情況僅設置可通過 checkError 方法測試的內部標誌,另外,爲了自動刷新,可以創建一個 PrintStream
③BufferedWriter:將文本寫入字符輸出流,緩衝各個字符從而提供單個字符,數組和字符串的高效寫入。通過write()方法可以將獲取到的字符輸出,然後通過newLine()進行換行操作。BufferedWriter中的字符流必須通過調用flush方法才能將其刷出去。並且BufferedWriter只能對字符流進行操作。如果要對字節流操作,則使用BufferedInputStream。
④PrintWriter的println方法自動添加換行,不會拋異常,若關心異常,需要調用checkError方法看是否有異常發生,PrintWriter構造方法可指定參數,實現自動刷新緩存(autoflush);

46. 什麼是節點流,什麼是處理流,它們各有什麼用處,處理流的創建有什麼特徵

節點流 直接與數據源相連,用於輸入或者輸出
處理流:在節點流的基礎上對之進行加工,進行一些功能的擴展處理流的構造器必須要 傳入節點流的子類

47. InputStream裏的read()返回的是什麼,read(byte[] data)是什麼意思,返回的是什麼值

返回的是所讀取的字節的int型(範圍0-255)read(byte [ ] data),將讀取的字節儲存在這個數組,返回的就是傳入數組參數個數Read字節讀取字節、字符讀取字符

48. OutputStream裏面的write()是什麼意思,write(byte b[], int off, int len)這個方法裏面的三個參數分別是什麼意思

write將指定字節傳入數據源
Byte b[ ]是byte數組
b[off]是傳入的第一個字符
b[off+len-1]是傳入的最後的一個字符
len是實際長度

49. 什麼是sql語句優化?

就是對性能低下的sql語句轉化成目的相同但是性能優異的語句。

50. sql優化的幾種方法

  • 對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。

  • 應儘量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
    select id from t where num is null
    可以在num上設置默認值0,確保表中num列沒有null值,然後這樣查詢:
    select id from t where num=0

  • 應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。

  • 應儘量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
    select id from t where num=10 or num=20
    可以這樣查詢:
    select id from t where num=10
    union all
    select id from t where num=20

  • in 和 not in 也要慎用,否則會導致全表掃描,如:
    select id from t where num in(1,2,3)
    對於連續的數值,能用 between 就不要用 in 了:
    select id from t where num between 1 and 3

  • 下面的查詢也將導致全表掃描:
    select id from t where name like ‘%abc%’

  • 應儘量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
    select id from t where num/2=100
    應改爲:
    select id from t where num=100*2

  • 應儘量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
    select id from t where substring(name,1,3)=‘abc’–name以abc開頭的id
    應改爲:
    select id from t where name like ‘abc%’

  • 不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。

  • 在使用索引字段作爲條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個字段作爲條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓字段順序與索引順序相一致。

  • 不要寫一些沒有意義的查詢,如需要生成一個空表結構:
    select col1,col2 into #t from t where 1=0
    這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
    create table #t(…)

  • 很多時候用 exists 代替 in 是一個好的選擇:
    select num from a where num in(select num from b)
    用下面的語句替換:
    select num from a where exists(select 1 from b where num=a.num)

  • 並不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重複時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那麼即使在sex上建了索引也對查詢效率起不了作用。

  • 索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因爲 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。
    一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

  • 儘量使用數字型字段,若只含數值信息的字段儘量不要設計爲字符型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因爲引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對於數字型而言只需要比較一次就夠了。

  • 儘可能的使用 varchar 代替 char ,因爲首先變長字段存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的字段內搜索效率顯然要高些。

  • 任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。

  • 避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

  • 在新建臨時表時,如果一次性插入數據量很大,那麼可以使用 select into 代替 create table,避免造成大量 log,以提高速度;如果數據量不大,爲了緩和系統表的資源,應先create table,然後insert。

  • 如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。

  • 儘量避免使用遊標,因爲遊標的效率較差,如果遊標操作的數據超過1萬行,那麼就應該考慮改寫。

  • 使用基於遊標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。

  • 與臨時表一樣,遊標並不是不可使用。對小型數據集使用 FAST_FORWARD 遊標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。

51. 爲何要進行sql優化

因爲sql語句是對數據庫進行操作的惟一途徑,對數據庫系統的性能起着決定性的作用,所以優化它,能夠提高訪問速度。

52. 如何找出需要優化的sql語句呢?

  • 開啓慢查詢日誌 :當一條sql執行超時時,mysql可以將慢的sql記錄到日誌中。
  • 使用執行計劃(explain)分析慢的原因:執行計劃能將 sql語句發送給mysql評估執行該條sql需要經歷哪些步驟消耗多少資源
  • show profile: 主要是用來查詢SQL在mysql服務器裏面的執行細節和生命週期情況
  • 數據庫服務器參數性能調優

53. 數據庫的表結構優化

  • 在創建表的屬性時,要選擇最合適的字段
    Mysql是一種關係型數據庫,可以很好地支 持大數據量的存儲,但是一般來說,數據庫中的表越小,在它上面執行的查詢也就越快。因此,在創建表的時候,爲了獲得更好的性能。
  • 儘量把字段設置爲NOT NULL
    在可能的情況下,儘量把字段設置爲NOT NULL,這樣在將來執行查詢的時候,數據庫不用去比較NULL值。
  • 創建索引
    • 索引是對數據庫表中一個或多個列的值進行排序的結構.使用索引查詢可以避免全表掃描。
    • 創建索引的語句: create index 創建名 on 表名字(字段名)。
    • 如果想查看當前表是否需要優化可以查看數據庫中查詢效率:

54. 數據庫的存儲引擎

MySQL中的數據用各種不同的技術存儲在文件(或者內存)中。這些技術中的每一種技術都使用不同的存儲機制、索引技巧、鎖定水平並且最終提供廣泛的不同的功能和能力。通過選擇不同的技術,你能夠獲得額外的速度或者功能,從而改善你的應用的整體功能。
查看數據庫的存儲引擎:SHOW VARIABLES LIKE ‘storage_engine’
常見的三種存儲引擎

  • InnoDB存儲引擎
  • MyISAM存儲引擎
  • MEMORY存儲引擎

55. 常用函數:

  • 數學函數:數學函數主要用於處理數字,包括整型、浮點數等。
  • 字符串函數:字符串函數是MySQL中最常用的一類函數,字符串函數主要用於處理表中的字符串。
  • 日期時間函數:MySQL的日期和時間函數主要用於處理日期時間。
  • 系統信息函數:系統信息函數用來查詢MySQL數據庫的系統信息。
  • 加密函數:加密函數是MySQL用來對數據進行加密的函數。

56. 數據庫三範式是什麼?

  • 第一範式(1NF):字段具有原子性,不可再分。所有關係型數據庫系統都滿足第一範式)
  • 第二範式(2NF):第二範式(2NF)是在第一範式(1NF)的基礎上建立起來的,即滿足第二範式(2NF)必須先滿足第一範式(1NF)。
    (要求數據庫表中的每個實例或行必須可以被惟一地區分。通常需要爲表加上一個列,以存儲各個實例的惟一標識。這個惟一屬性列被稱爲主關鍵字或主鍵。第二範式(2NF)要求實體的屬性完全依賴於主關鍵字。所謂完全依賴是指不能存在僅依賴主關鍵字一部分的屬性,如果存在,那麼這個屬性和主關鍵字的這一部分應該分離出來形成一個新的實體,新實體與原實體之間是一對多的關係。爲實現區分通常需要爲表加上一個列,以存儲各個實例的惟一標識。簡而言之,第二範式就是非主屬性非部分依賴於主關鍵字。)
  • 第三範式的要求:滿足第三範式(3NF)必須先滿足第二範式(2NF)。簡而言之,第三範式(3NF)要求一個數據庫表中不包含已在其它表中已包含的非主關鍵字信息。
    所以第三範式具有如下特徵:
    1).每一列只有一個值
    2).每一行都能區分。
    3).每一個表都不包含其他表已經包含的非主關鍵字信息。

57. 說出一些數據庫優化方面的經驗?

用PreparedStatement 一般來說比Statement性能高:一個sql 發給服務器去執行,涉及步驟:
語法檢查、語義分析, 編譯,緩存有外鍵約束會影響插入和刪除性能,如果程序能夠保證數據的完整性,那在設計數據庫時就去掉外鍵。(比喻:就好比免檢產品,就是爲了提高效率,充分相信產品的製造商)表中允許適當冗餘;sql語句全部大寫,特別是列名和表名都大寫。

58. Dubbo是什麼?

DUBBO是一個分佈式服務框架,致力於提供高性能和透明化的RPC(遠程過程調用協議)遠程服務調用方案,是阿里巴巴SOA服務化治理方案的核心框架。
說白了就是個遠程服務調用的分佈式框架。其核心部分包含:

  • 遠程通訊: 提供對多種基於長連接的NIO框架抽象封裝,包括多種線程模型,序列化,以及“請求-響應”模式的信息交換方式。
  • 集羣容錯: 提供基於接口方法的透明遠程過程調用,包括多協議支持,以及軟負載均衡,失敗容錯,地址路由,動態配置等集羣支持。
  • 自動發現: 基於註冊中心目錄服務,使服務消費方能動態的查找服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。

59. 爲什麼要用Dubbo(優點和好處),解決什麼問題?

Dubbo提供了三個關鍵功能:基於接口的遠程調用,容錯與負載均衡,服務自動註冊與發現。

  • 透明化的遠程方法調用,就像調用本地方法一樣調用遠程方法,只需簡單配置,沒有任何API侵入。
  • 軟負載均衡及容錯機制,可在內網替代F5等硬件負載均衡器,降低成本,減少單點。
  • 服務自動註冊與發現,不再需要寫死服務提供方地址,註冊中心基於接口名查詢服務提供者的IP地址,並且能夠平滑添加或刪除服務提供者。

60. Dubbo如何暴露與發現服務?(一定要懂)

節點角色說明:

  • Provider: 暴露服務的服務提供方。
  • Consumer: 調用遠程服務的服務消費方。
  • Registry: 服務註冊與發現的註冊中心。
  • Monitor: 統計服務的調用次調和調用時間的監控中心。
  • Container: 服務運行容器。
    調用關係說明:
  • 服務容器負責啓動,加載,運行服務提供者。
  • 服務提供者在啓動時,向註冊中心註冊自己提供的服務。
  • 服務消費者在啓動時,向註冊中心訂閱自己所需的服務。
  • 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推
    送變更數據給消費者。
  • 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,
    如果調用失敗,再選另一臺調用。
  • 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計
    數據到監控中心。

61. Dubbo 和 Spring Cloud 有什麼區別?

Dubbo 使用的是 RPC 通信,而 Spring Cloud 使用的是 HTTP RESTFul 方式。這兩種方式各有優劣。對於類似於電商等同步調用場景多並且能支撐搭建Dubbo 這套比較複雜環境的成本的產品而言,Dubbo 確實是一個可以考慮的選擇。雖然在一定程度上來說Spring Cloud犧牲了服務調用的性能,但也避免了上面提到的原生RPC帶來的問題。而且REST相比RPC更爲靈活,服務提供方和調用方的依賴只依靠一紙契約,不存在代碼級別的強依賴,這在強調快速演化的微服務環境下,顯得更爲合適。

62. Dubbo 支持的通信協議有哪些?

  • dubbo協議(默認),使用NIO異步通信,單一長連接,hessian序列化協議,使用在傳輸數據量較小(每次請求在100kb以內),但是併發量很高的場景。
  • rmi(Remote Method Invocation 遠程方法調用)java二進制序列化,使用在多個短連接,使用在消費者和提供者數量差不多的情況,適用於文件的傳輸,一般比較少用。
  • hessian協議,hessian序列化協議,多個短連接,使用在提供者比消費者數量還多的請你趕快,適用於文件傳輸,一般比較少用。

63. 怎麼實現遠程通信

遠程通信:簡單來說,就是一個系統去調用另一個系統中的數據。
常見的有三種方式:

  • Webservice的方式:
    • 優點:跨語言跨平臺
    • 缺點:它是基於soap協議的,使用http+xml的方式進行數據傳輸,http是應用層協議,傳輸效率不是很高,而且xml的解析也比 較費時,所以項目內部進行通信的時候,不建議使用Websservice的方式
  • restful形式的服務:
    • 優點:restful本身就是http,使用的是http+json的方式進行數據傳輸,因爲json數據本身是非常簡潔的,所以它比webservice的 傳輸效率更高;手機app端一般都使用該方法,其他很多項目也是用這種方式
    • 缺點:如果服務太多的話,會出現服務之間調用關係混亂,此時就需要治理服務
  • Dubbo:使用的是RPC協議進行遠程調用,RPC協議是一個二進制協議,直接使用的socket進行通信,傳輸效率高,並且可以統計出系統 之間的調用關係和調用次數系統分佈式SAO系統的內部通信推薦使用dubbo

64. Dubbo爲什麼使用異步單一長連接?

Dubbo缺省協議採用單一長連接和NIO異步通訊,適合於小數據量大併發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的情況。

65. Dubbo有哪幾種集羣容錯方案,默認是哪種?

  • Failover Cluster:失敗重試
    當服務消費方調用服務提供者失敗後自動切換到其他服務提供者服務器進行重試。這通常用於讀操作或者具有冪等的寫操作,需要注意的是重試會帶來更長延遲。可通過 retries=“2” 來設置重試次數(不含第一次)。
  • Failfast Cluster:快速失敗
    當服務消費方調用服務提供者失敗後,立即報錯,也就是隻調用一次。通常這種模式用於非冪等性的寫操作。
  • Failsafe Cluster:失敗安全
    當服務消費者調用服務出現異常時,直接忽略異常。這種模式通常用於寫入審計日誌等操作。
  • Failback Cluster:失敗自動恢復
    當服務消費端用服務出現異常後,在後臺記錄失敗的請求,並按照一定的策略後期再進行重試。這種模式通常用於消息通知操作。
  • Forking Cluster:並行調用
    當消費方調用一個接口方法後,Dubbo Client會並行調用多個服務提供者的服務,只要一個成功即返回。這種模式通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks=“2” 來設置最大並行數。
  • Broadcast Cluster:廣播調用
    當消費者調用一個接口方法後,Dubbo Client會逐個調用所有服務提供者,任意一臺調用異常則這次調用就標誌失敗。這種模式通常用於通知所有提供者更新緩存或日誌等本地資源信息。
    如上,Dubbo本身提供了豐富的集羣容錯模式,但是如果您有定製化需求,可以根據Dubbo提供的擴展接口Cluster進行定製。

66. Dubbo的異常機制是什麼?

Dubbo有一個名爲ExceptionFilter的異常過濾器,包含如下機制:

  • 如果是checked異常,直接拋出!
  • 在方法簽名上有聲明,直接拋出 throws MyCustomException
  • 異常類和接口類在同一jar包裏,直接拋出
  • 是JDK自帶的異常,直接拋出(className.startsWith(“java.”) || className.startsWith(“javax.”))
  • 是Dubbo本身的異常,直接拋出(RpcException)
  • 其他異常通過RuntimeException

67. 掛機_Dubbo掛機了怎麼處理

首先zookeeper掛了還能調用服務,在啓動dubbo時,消費者會從zk拉取註冊的生產者的地址接口等數據,緩存在本地。每次調用時,按照本地存儲的地址進行調用。但是在註冊中心全部掛掉後增加新的提供者,則不能被消費者發現.(前提是你沒有增加新的服務,如果你要調用新的服務,則是不能辦到的。

68. 安全_dubbo+zookeeper如何解決不同系統間調用的安全性問題

Dubbo通過Token令牌防止用戶繞過註冊中心直連,然後在註冊中心上管理授權。

  • 可以全局設置開啓令牌驗證:

<dubbo:provider interface=“com.foo.BarService” token=“true” />

<dubbo:provider interface=“com.foo.BarService” token=“123456” />

  • 也可在服務級別設置:

<dubbo:service interface=“com.foo.BarService” token=“true” />

<dubbo:service interface=“com.foo.BarService” token=“123456” />

  • 還可在協議級別設置:

<dubbo:protocol name=“dubbo” token=“true” />

<dubbo:protocol name=“dubbo” token=“123456” />

69. Zookeeper 介紹(談談你對zookeeper的瞭解)

官方推薦使用 zookeeper 註冊中心。註冊中心負責服務地址的註冊與查找,相當於目錄服務,服務提供者和消費者只在啓動時與註冊中心交互,註冊中心不轉發請求,壓力較小。
Zookeeper 是 Apacahe Hadoop 的子項目,是一個樹型的目錄服務,支持變更推送,適合作爲Dubbox 服務的註冊中心,工業強度較高,可用於生產環境。

70. 作用_zookeeper註冊中心的作用?端口是多少

  • 作用:Zookeeper註冊中心的作用主要就是註冊和發現服務的作用。類似於房產中介的作用,在系統中並不參與服務的調用及數據的傳輸。
  • 端口及作用
    • 2181:對cline端提供服務
    • 3888:選舉leader使用
    • 2888:集羣內機器通訊使用(Leader監聽此端口)

71. zookeeper在項目中怎麼用的

  • 作爲dubbo的註冊中心,暴露服務,然後消費方訂閱服務用的
  • 作爲solr集羣的調配中心,達到負載均衡的效果

72. 缺陷_zookeeper存在什麼缺陷

  • 本身不是爲高可用性設計,master撐不住高流量容易導致系統crash;
  • zookeeper的選舉過程速度很慢;
  • 難以避免數據的不一致;
  • zookeeper的性能是有限的

73. springmvc框架的工作流程

  • 方式一:
    • 用戶向服務器發送請求,請求被 SpringMVC的前端控制器 DispatcherServlet截獲。
    • DispatcherServlet對請求的 URL(統一資源定位符)進行解析,得到 URI(請求資源標識符),然後根據該 URI,調用 HandlerMapping獲得該 Handler配置的所有相關的對象,包括 Handler對象以及 Handler對象對應的攔截器,這些對象都會被封裝到一個 HandlerExecutionChain對象當中返回。
    • DispatcherServlet根據獲得的 Handler,選擇一個合適的 HandlerAdapter。HandlerAdapter的設計符合面向對象中的單一職責原則,代碼結構清晰,便於維護,最爲重要的是,代碼的可複製性高。HandlerAdapter會被用於處理多種 Handler,調用 Handler實際處理請求的方法。
    • 提取請求中的模型數據,開始執行 Handler(Controller)。在填充 Handler的入參過程中,根據配置,spring將幫助做一些額外的工作
      消息轉換:將請求的消息,如 json、xml等數據轉換成一個對象,將對象轉換爲指定的響應信息。
      數據轉換:對請求消息進行數據轉換,如 String轉換成 Integer、Double等。
      數據格式化:對請求的消息進行數據格式化,如將字符串轉換爲格式化數字或格式化日期等。
      數據驗證:驗證數據的有效性如長度、格式等,驗證結果存儲到 BindingResult或 Error中。
    • Handler執行完成後,向 DispatcherServlet返回一個 ModelAndView對象ModelAndView對象中應該包含視圖名或視圖模型。
    • 根據返回的ModelAndView對象,選擇一個合適的 ViewResolver(視圖解析器) 返回給
      DispatcherServlet。
    • ViewResolver結合 Model和 View來渲染視圖。
    • 將視圖渲染結果返回給客戶端。
      以上 8個步驟,DispatcherServlet、HandlerMapping、HandlerAdapter和 ViewResolver等對象協同工
      作,完成 SpringMVC請求—>響應的整個工作流程,這些對象完成的工作對於開發者來說都是不可
      見的,開發者並不需要關心這些對象是如何工作的,開發者,只需要在 Handler(Controller)當中完成對請求的業務處理。
  • 方式二:
    • 用戶發送請求至前端控制器DispatcherServlet;
    • DispatcherServlet收到請求後,調用HandlerMapping處理器映射器,請求獲取Handle;
    • 處理器映射器根據請求url找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一併返回給DispatcherServlet;
    • DispatcherServlet 調用 HandlerAdapter處理器適配器;
    • HandlerAdapter 經過適配調用 具體處理器(Handler,也叫後端控制器);
    • Handler執行完成返回ModelAndView;
    • HandlerAdapter將Handler執行結果ModelAndView返回給DispatcherServlet;
    • DispatcherServlet將ModelAndView傳給ViewResolver視圖解析器進行解析;
    • ViewResolver解析後返回具體View;
    • DispatcherServlet對View進行渲染視圖(即將模型數據填充至視圖中)
    • DispatcherServlet響應用戶。

74. 什麼是Spring MVC ?簡單介紹下你對springMVC的理解?

Spring MVC是一個基於Java的實現了MVC設計模式的請求驅動類型的輕量級Web框架,通過把Model,View,Controller分離,將web層進行職責解耦,把複雜的web應用分成邏輯清晰的幾部分,簡化開發,減少出錯,方便組內開發人員之間的配合。

75. Springmvc有什麼優點:

  • 可以支持各種視圖技術,而不僅僅侷限於JSP;
  • 與Spring框架集成(如IoC容器、AOP等);
  • 清晰的角色分配:前端控制器(dispatcherServlet) , 請求到處理器映射(handlerMapping), 處理器適配器(HandlerAdapter), 視圖解析器(ViewResolver)。
  • 支持各種請求資源的映射策略。

76. Spring MVC的主要組件?

  • 前端控制器 DispatcherServlet(不需要程序員開發)
    作用:接收請求、響應結果,相當於轉發器,有了DispatcherServlet 就減少了其它組件之間的耦合度。
  • 處理器映射器HandlerMapping(不需要程序員開發)
    作用:根據請求的URL來查找Handler
  • 處理器適配器HandlerAdapter
    注意:在編寫Handler的時候要按照HandlerAdapter要求的規則去編寫,這樣適配器HandlerAdapter纔可以正確的去執行Handler。
  • 處理器Handler(需要程序員開發)
  • 視圖解析器 ViewResolver(不需要程序員開發)
    作用:進行視圖的解析,根據視圖邏輯名解析成真正的視圖(view)
  • 視圖View(需要程序員開發jsp)
    View是一個接口, 它的實現類支持不同的視圖類型(jsp,freemarker,pdf等等)

77. springMVC和struts2的區別有哪些?

  • springmvc的入口是一個servlet即前端控制器(DispatchServlet),而struts2入口是一個filter過慮器(StrutsPrepareAndExecuteFilter)。
  • springmvc是基於方法開發(一個url對應一個方法),請求參數傳遞到方法的形參,可以設計爲單例或多例(建議單例),struts2是基於類開發,傳遞參數是通過類的屬性,只能設計爲多例。
  • Struts採用值棧存儲請求和響應的數據,通過OGNL存取數據,springmvc通過參數解析器是將request請求內容解析,並給方法形參賦值,將數據和視圖封裝成ModelAndView對象,最後又將ModelAndView中的模型數據通過reques域傳輸到頁面。Jsp視圖解析器默認使用jstl。

78. SpringMVC怎麼樣設定重定向和轉發的?

  • 轉發:在返回值前面加"forward:",譬如"forward:user.do?name=method4"
  • 重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"

79. SpringMvc怎麼和AJAX相互調用的?

通過Jackson框架就可以把Java裏面的對象直接轉化成Js可以識別的Json對象。具體步驟如下 :

  • 加入Jackson.jar
  • 在配置文件中配置json的映射
  • 在接受Ajax方法裏面可以直接返回Object,List等,但方法前面要加上@ResponseBody註解。

80. 如何解決POST請求中文亂碼問題,GET的又如何處理呢?

  • 解決post請求亂碼問題:
    在web.xml中配置一個CharacterEncodingFilter過濾器,設置成utf-8;
  • get請求中文參數出現亂碼解決方法有兩個:
    • 修改tomcat配置文件添加編碼與工程編碼一致
    • 另外一種方法對參數進行重新編碼:

81. Spring MVC的異常處理?

可以將異常拋給Spring框架,由Spring框架來處理;我們只需要配置簡單的異常處理器,在異常處理器中添視圖頁面即可。

82. SpringMvc的控制器是不是單例模式,如果是,有什麼問題,怎麼解決?

是單例模式,所以在多線程訪問的時候有線程安全問題,不要用同步,會影響性能的,解決方案是在控制器裏面不能寫字段。

83. SpringMVC常用的註解有哪些?

  • @RequestMapping:用於處理請求 url 映射的註解,可用於類或方法上。用於類上,則表示類中的所有響應請求的方法都是以該地址作爲父路徑。
  • @RequestBody:註解實現接收http請求的json數據,將json轉換爲java對象。
  • @ResponseBody:註解實現將conreoller方法返回對象轉化爲json對象響應給客戶。

84. SpingMvc中的控制器的註解一般用那個,有沒有別的註解可以替代?

一般用@Conntroller註解,表示是表現層,不能用別的註解代替。

85. 如果在攔截請求中,我想攔截get方式提交的方法,怎麼配置?

可以在@RequestMapping註解裏面加上method=RequestMethod.GET。

86. 怎樣在方法裏面得到Request,或者Session?

直接在方法的形參中聲明request,SpringMvc就自動把request對象傳入。

87. 如果想在攔截的方法裏面得到從前臺傳入的參數,怎麼得到?

直接在形參裏面聲明這個參數就可以,但必須名字和傳過來的參數一樣。

88. 如果前臺有很多個參數傳入,並且這些參數都是一個對象的,那麼怎麼樣快速得到這個對象?

直接在方法中聲明這個對象,SpringMvc就自動會把屬性賦值到這個對象裏面。

89. SpringMvc中函數的返回值是什麼?

返回值可以有很多類型,有String, ModelAndView。ModelAndView類把視圖和數據都合併的一起的,但一般用String比較好。

90. SpringMvc用什麼對象從後臺向前臺傳遞數據的?

通過ModelMap對象,可以在這個對象裏面調用put方法,把對象加到裏面,前臺就可以通過el表達式拿到。

91. 怎麼樣把ModelMap裏面的數據放入Session裏面?

可以在類上面加上@SessionAttributes註解,裏面包含的字符串就是要放入session裏面的key。

92. SpringMvc裏面攔截器是怎麼寫的:

有兩種寫法:①一種是實現HandlerInterceptor接口;②另外一種是繼承適配器類,接着在接口方法當中,實現處理邏輯;然後在SpringMvc的配置文件中配置攔截器即可:

93. 註解原理:

註解本質是一個繼承了Annotation的特殊接口,其具體實現類是Java運行時生成的動態代理類。我們通過反射獲取註解時,返回的是Java運行時生成的動態代理對象。通過代理對象調用自定義註解的方法,會最終調用AnnotationInvocationHandler的invoke方法。該方法會從memberValues這個Map中索引出對應的值。而memberValues的來源是Java常量池。

94. 什麼是Mybatis?

  • Mybatis是一個半ORM(對象關係映射)框架,它內部封裝了JDBC,開發時只需要關注SQL語句本身,不需要花費精力去處理加載驅動、創建連接、創建statement等繁雜的過程。程序員直接編寫原生態sql,可以嚴格控制sql執行性能,靈活度高。
  • MyBatis 可以使用 XML 或註解來配置和映射原生信息,將 POJO映射成數據庫中的記錄,避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。
  • 通過xml 文件或註解的方式將要執行的各種 statement 配置起來,並通過java對象和 statement中sql的動態參數進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射爲java對象並返回。(從執行sql到返回result的過程)。

95. Mybaits有什麼優點:

  • 基於SQL語句編程,相當靈活,不會對應用程序或者數據庫的現有設計造成任何影響,SQL寫在XML裏,解除sql與程序代碼的耦合,便於統一管理;提供XML標籤,支持編寫動態SQL語句,並可重用。
  • 與JDBC相比,減少了50%以上的代碼量,消除了JDBC大量冗餘的代碼,不需要手動開關連接;
  • 很好的與各種數據庫兼容(因爲MyBatis使用JDBC來連接數據庫,所以只要JDBC支持的數據庫MyBatis都支持)。
  • 能夠與Spring很好的集成;
  • 提供映射標籤,支持對象與數據庫的ORM字段關係映射;提供對象關係映射標籤,支持對象關係組件維護。

96. MyBatis框架的缺點:

  • SQL語句的編寫工作量較大,尤其當字段多、關聯表多時,對開發人員編寫SQL語句的功底有一定要求。
  • SQL語句依賴於數據庫,導致數據庫移植性差,不能隨意更換數據庫。

97. MyBatis框架適用場合:

  • MyBatis專注於SQL本身,是一個足夠靈活的DAO層解決方案。
  • 對性能的要求很高,或者需求變化較多的項目,如互聯網項目,MyBatis將是不錯的選擇。

98. MyBatis與Hibernate有哪些不同?

  • Mybatis和hibernate不同,它不完全是一個ORM框架,因爲MyBatis需要程序員自己編寫Sql語句。
  • Mybatis直接編寫原生態sql,可以嚴格控制sql執行性能,靈活度高,非常適合對關係數據模型要求不高的軟件開發,因爲這類軟件需求變化頻繁,一但需求變化要求迅速輸出成果。但是靈活的前提是mybatis無法做到數據庫無關性,如果需要實現支持多種數據庫的軟件,則需要自定義多套sql映射文件,工作量大。
  • Hibernate對象/關係映射能力強,數據庫無關性好,對於關係模型要求高的軟件,如果用hibernate開發可以節省很多代碼,提高效率。

99. #{}和${}的區別是什麼?

#{}是預編譯處理,${}是字符串替換。
Mybatis在處理#{}時,會將sql中的#{}替換爲?號,調用PreparedStatement的set方法來賦值;
Mybatis在處理{}時,就是把{}替換成變量的值。使用#{}可以有效的防止SQL注入,提高系統安全性。

100. 當實體類中的屬性名和表中的字段名不一樣 ,怎麼辦 ?

  • 通過在查詢的sql語句中定義字段名的別名,讓字段名的別名和實體類的屬性名一致。
  • 通過來映射字段名和實體類屬性名的一一對應的關係。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章