Java面试题附答案(面试必会)
Java面試題大全
- JavaSE
- 1.JDK和JRE區別
- 2.八大數據類型
- 3.equals和==區別
- 4.String類的常用方法
- 5.String不可變原理
- 6.線程池三大方法,七大參數,四種拒絕策略
- 7.ArrayList 和LinkedList 區別以及底層原理
- 8.類的實例化順序
- 9.synchronized 和 ReentrantLock 區別是什么?
- 10.HashMap底層原理(重點)
- 11.HashMap的put(k,v)實現原理
- 12.HashMap的get(k,v)實現原理
- 13.Volatile
- 14.線程幾種狀態,什么時候會阻塞
- 15.為什么阿里巴巴Java手冊不建議使用Executors創建線程池?
- 16.類加載過程
- 17.Java中final、finally、finalize的區別與用法
- 18.java中String、StringBuffer和StringBuilder的區別
- 19.線程安不安全指什么
- 20.Session 與 Token 的區別
- 21.java中四種修飾符的限制范圍
- 22.Object 類中的方法
- 23.線程如何通信(面試常問)
- 24.do while 和while的區別
- 25.Continue和Break區別
- 26. 面向對象的特征
- 27.Java創建對象有幾種方式?
- 28. Java 中 IO 流分為幾種?
- 29.BIO、NIO、AIO 有什么區別?
- 計算機網絡
- 1.TCP三次握手,四次揮手
- 2.TCP和UDP區別以及長、短連接
- 3.OSI七層模型和TCP/IP四層協議
- 4.HTTP常見狀態碼
- 5.進程三種狀態
- 6.進程和線程,進程可以沒有線程嗎
- 7.從輸入URL到頁面展示的詳細過程
- JVM
- g1 和 cms 區別
- JVM內存模型以及GC算法
- 數據庫(MySql、Redis)
- 1.數據庫三種刪除方式及其區別
- 2.事務的隔離級別
- 3.MYSQL的兩種存儲引擎區別(事務、鎖級別等等),各自的適用場景
- 4.索引的好處以及適合使用的場景
- 5.最左匹配原則
- 6.死鎖怎么解決
- 7.limit分頁
- 8. 分組查詢,聚合函數
- 9. where和having區別
- 10.有哪些數據庫優化方式(重點)
- 11.索引
- 12.數據庫的三范式是什么(重要)
- 13.SQL優化
- 14.什么是內聯接、左外聯接、右外聯接?
- 數據結構
- 數組和鏈表區別,單鏈表和雙鏈表
- 什么是紅黑樹
- 版本管理工具(git)
- git命令以及分區
- 框架
- 1.SpringMVC執行原理
- 2.SpringBoot自動裝配原理
- 3.SpringBoot常用注解
- 4.GET和POST的區別
- 5.threadlocal原理以及內存泄漏怎么解決
- 6.Spring中 bean生命周期
- 7.Mybatis中的 ${} 和 #{}區別與用法
- 8.什么是Nginx
- 9. Nginx的應用場景
- 10.什么是 JWT (JSON WEB TOKEN)
- 11.MyBatis 與 Hibernate 有哪些不同?
- 12.通常一個 Xml 映射文件,都會寫一個 Dao 接口與之對應, 這個 Dao 接口的工作原理是什么?Dao 接口里的方法, 參數不同時,方法能重載嗎?
- 13.Mybatis 的一級、二級緩存
- 14.什么是 MyBatis 的接口綁定?有哪些實現方式?
- 15.Spring Boot 的核心注解是哪個?它主要由哪幾個注解組成的?
- 16.什么是 CSRF 攻擊?
- 17.RequestMapping 和 GetMapping 的不同之處在哪里?
- 消息隊列RabbitMQ
- 1.什么是 rabbitmq,為什么要使用?
- 2. rabbitmq 的使用場景
- 3.如何避免消息重復投遞或重復消費?
- 4.消息基于什么傳輸?
- 5.Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么區別?
JavaSE
1.JDK和JRE區別
JRE(Java Runtime Enviroment)是運行Java程序所必須環境的集合,包含JVM標準實現及 Java核心類庫。它包括Java虛擬機、Java平臺核心類和支持文件。它不包含開發工具(編譯器、調試器等)。
JDK(Java Development Kit)是Java開發工具包,它提供了Java的開發環境(提供了編譯器javac等工具,用于將java文件編譯為class文件)和運行環境(提供了JVM和Runtime輔助包,用于解析class文件使其得到運行)。
2.八大數據類型
分別是byte, short, int, long, char, float, double, boolean.
1.byte
byte屬于Java中的整型,長度為1字節8bit,取值10000000(-128)到 01111111(127),變量初始化默認值為0,包裝類Byte
2.short
short屬于Java中的整型,長度為2字節16bit,取值10000000 00000000(-32768)到 01111111 11111111(32767),變量初始化默認值為0,包裝類Short
3.int
int屬于Java中的整型,長度為4字節32bit,取值-2^31 (-2,147,483,648)到 2^31-1(2,147,483,647),變量初始化默認值為0,包裝類Integer
4.long
long屬于Java中的整型,長度為8字節 64bit,取值-2^63 (-9,223,372,036,854,775,808?)到 2^63-1(9,223,372,036,854,775,8087),變量初始化默認值為0或0L,包裝類Long
5.float
float屬于Java中的浮點型,也叫單精度浮點型,長度為4字節 32bit,變量初始化默認值0.0f,包裝類Float,取值2-128~2128
6.double
double屬于Java中的浮點型,也叫雙精度浮點型,長度為8字節 64bit,變量初始化默認值0.0d,包裝類Double,取值2-1024~21024
7.char
char屬于java中的字符型,占2字節 16bit,可以賦值單字符以及整型數值, 變量初始化無默認值,包裝類Character。
如:
char a = ‘a’;
char a = ‘中’;
char a = 12; // 取值范圍0~65536,因為char類型在ASCII字符編碼中,有對應的數值,可直接做運算,輸出字符表中對應的字符
8.boolean
在JVM中并沒有提供boolean專用的字節碼指令,而boolean類型數據在經過編譯后在JVM中會通過int類型來表示,此時boolean數據4字節32位,而boolean數組將會被編碼成Java虛擬機的byte數組,此時每個boolean數據1字節占8bit.
僅有兩個值true, false,變量初始化默認值false
3.equals和==區別
對于==,一般比較的是值是否相等 如果作用于基本數據類型的變量,則直接比較其存儲的 “值”是否相等; 如果作用于引用類型的變量,則比較的是所指向的對象的地址
對于equals方法,一般為比較內容是否相同 如果沒有對equals方法進行重寫,則比較的是引用類型的變量所指向的對象的地址; 諸如String、Date等類對equals方法進行了重寫的話,比較的是所指向的對象的內容。
4.String類的常用方法
- public int length() //返回該字符串的長度
- public char charAt(int index) //返回字符串中指定位置的字符;注意字符串中第一個字符索引是0,最后一個是length()-1。
- public int compareTo(String anotherString) //該方法是對字符串內容按字典順序進行大小比較,通過返回的整數值指明當前字符串與參數字符串的大小關系。若當前對象比參數大則返回正整數,反之返回負整數,相等返回0。
- public String toLowerCase()//返回將當前字符串中所有字符轉換成小寫后的新串
- public String toUpperCase()//返回將當前字符串中所有字符轉換成大寫后的新串
- public String substring(int beginIndex)//該方法從beginIndex位置起,從當前字符串中取出剩余的字符作為一個新的字符串返回。
5.String不可變原理
String 被聲明為 final,因此它不可被繼承。(Integer 等包裝類也不能被繼承)
之所以設計成不可變,是為了安全,保證了線程安全,以及讓常量池有意義
string不可變的設計出于性能考慮,當然背后的原理是string pool,當然string pool不可能使string類不可變,不可變的string更好的提高性能。
6.線程池三大方法,七大參數,四種拒絕策略
具體答案參考我之前的文章https://blog.csdn.net/JiaMing11_27/article/details/119078588?spm=1001.2014.3001.5501
7.ArrayList 和LinkedList 區別以及底層原理
ArrayList和LinkedList 都實現了list的接口,Al底層是數組,時間復雜度是O(1),Lk底層數據結構是雙向循環鏈表 ,鏈表只有一個前驅和后繼,時間復雜度O(n)。
相對來說,Al是數組查找更容易,Lk因為是鏈表,所以插入、刪除比較容易,但是更占內存,因為每一個節點存儲了兩個引用 ,一個指向前一個元素 一個后。
8.類的實例化順序
父類靜態代變量 父類靜態代碼塊 子類靜態變量 子類靜態代碼塊
父類非靜態變量 父類構造函數 子類非靜態變量 子類構造
9.synchronized 和 ReentrantLock 區別是什么?
1.ReentrantLock 是 API 級別的,synchronized 是 JVM 級別的
2. ReentrantLock 可以實現公平鎖
3 ReentrantLock 通過 Condition 可以綁定多個條件
4. 底層實現不一樣, synchronized 是同步阻塞,使用的是悲觀并發策略,lock 是同步非阻塞,采用的是樂觀并發策略
5. Lock 是一個接口,而 synchronized 是 Java 中的關鍵字,synchronized 是內置的語言實現。
6. synchronized 在發生異常時,會自動釋放線程占有的鎖,因此不會導致死鎖現象發生;
而 Lock 在發生異常時,如果沒有主動通過 unLock()去釋放鎖,則很可能造成死鎖現象,
因此使用 Lock 時需要在 finally 塊中釋放鎖。
7.通過 Lock 可以知道有沒有成功獲取鎖,而 synchronized 卻無法辦到。
10.HashMap底層原理(重點)
hashMap是線程不安全的,HashMap是數組+鏈表+紅黑樹(JDK1.8增加了紅黑樹部分)實現的,采用哈希表來存儲的,hashMap是根據鍵的hashCode值存儲數據,又很快的訪問速度,但是遍歷順序不確定 hashMap是一對一或一對多的關系 鍵只允許有一個空值 value可以有多個 當鍵相同時 會覆蓋掉value值
底層實現原理:
HashMap4種構造方法 指定初始大小和負載因子 指定初始大小和默認負載因子 都采用默認值 容量默認16 為了減少hash碰撞次數,折中,均勻泊松分布 。負載因子默認0.75 ,因為0.5 元素達到一半就擴容 擴容太浪費資源 ,查詢效率會增加,但是空間利用率低 。1.0時空間利用率高了,但是耗費時間 。
11.HashMap的put(k,v)實現原理
(1)首先將k,v封裝到Node對象當中(節點)。
(2)然后它的底層會調用K的hashCode()方法得出hash值。
(3)通過哈希表函數/哈希算法,將hash值轉換成數組的下標,下標位置上如果沒有任何元素,就把Node添加到這個位置上。如果說下標對應的位置上有鏈表。此時,就會拿著k和鏈表上每個節點的k進行equal。如果所有的equals方法返回都是false,那么這個新的節點將被添加到鏈表的末尾。如其中有一個equals返回了true,那么這個節點的value將會被覆蓋。
12.HashMap的get(k,v)實現原理
(1)先調用k的hashCode()方法得出哈希值,并通過哈希算法轉換成數組的下標。
(2)通過上一步哈希算法轉換成數組的下標之后,在通過數組下標快速定位到某個位置上。如果這個位置上什么都沒有,則返回null。如果這個位置上有單向鏈表,那么它就會拿著K和單向鏈表上的每一個節點的K進行equals,如果所有equals方法都返回false,則get方法返回null。如果其中一個節點的K和參數K進行equals返回true,那么此時該節點的value就是我們要找的value了,get方法最終返回這個要找的value。
13.Volatile
jvm提供的輕量級同步機制
三個特性:保證可見性 不保證原子性 禁止指令重排
14.線程幾種狀態,什么時候會阻塞
在Java當中,線程通常都有五種狀態,創建、就緒、運行、阻塞和死亡。
第一是創建狀態。在生成線程對象,并沒有調用該對象的start方法,這是線程處于創建狀態;
第二是就緒狀態。當調用了線程對象的start方法之后,該線程就進入了就緒狀態,但是此時線程調度程序還沒有把該線程設置為當前線程,此時處于就緒狀態。在線程運行之后,等待或者睡眠中回來之后,也會處于就緒狀態
第三是運行狀態。線程調度程序將處于就緒狀態的線程設置為當前線程,此時線程就進入了運行狀態,開始運行run函數當中的代碼。
第四是阻塞狀態。線程正在運行的時候,被暫停,通常是為了等待某個時間的發生(比如說某項資源就緒)之后再繼續運行。sleep,suspend等方法都可以導致線程阻塞。
第五是死亡狀態。如果一個線程的run方法執行結束,該線程就會死亡。對于已經死亡的線程,無法再使用start方法令其進入就緒狀態。
15.為什么阿里巴巴Java手冊不建議使用Executors創建線程池?
FixedThreadPool和SingleThreadExecutor => 允許的請求隊列長度為Integer.MAX_VALUE,可能會堆積大量的請求,從而引起OOM異常
CachedThreadPool => 允許創建的線程數為Integer.MAX_VALUE,可能會創建大量的線程,從而引起OOM異常,這就是為什么禁止使用Executors去創建線程池,而是推薦自己去創建ThreadPoolExecutor的原因。
16.類加載過程
JVM類加載機制定義:
虛擬機把描述類的數據從Class文件加載到內存,并對數據進行校驗、轉換解析和初始化,最終形成可被虛擬機直接使用的Java類型的過程
類從被加載到虛擬機內存中開始、到卸載出內存為止,整個生命周期包括七個階段:
- 加載
- 驗證
- 準備
- 解析
- 初始化
- 使用
- 卸載
17.Java中final、finally、finalize的區別與用法
final:java中的關鍵字,修飾符。
A).如果一個類被聲明為final,就意味著它不能再派生出新的子類,不能作為父類被繼承。因此,一個類不能同時被聲明為abstract抽象類的和final的類。
B).如果將變量或者方法聲明為final,可以保證它們在使用中不被改變.
1)被聲明為final的變量必須在聲明時給定初值,而在以后的引用中只能讀取,不可修改。
2)被聲明final的方法只能使用,不能重載。
finally:java的一種異常處理機制。
finally是對Java異常處理模型的最佳補充。finally結構使代碼總會執行,而不管無異常發生。使用finally可以維護對象的內部狀態,并可以清理非內存資源。特別是在關閉數據庫連接這方面,如果程序員把數據庫連接的close()方法放到finally中,就會大大降低程序出錯的幾率。
finalize:Java中的一個方法名。
Java技術使用finalize()方法在垃圾收集器將對象從內存中清除出去前,做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒被引用時對這個對象調用的。它是在Object類中定義的,因此所的類都繼承了它。子類覆蓋finalize()方法以整理系統資源或者執行其他清理工作。
finalize()方法是在垃圾收集器刪除對象之前對這個對象調用的。
18.java中String、StringBuffer和StringBuilder的區別
StringBuffer是線程安全,可以不需要額外的同步用于多線程中;
StringBuilder是非同步,運行于多線程中就需要使用著單獨同步處理,但是速度就比StringBuffer快多了;
StringBuffer與StringBuilder兩者共同之處:可以通過append、indert進行字符串的操作。
String實現了三個接口:Serializable、Comparable、CarSequence
StringBuilder只實現了兩個接口Serializable、CharSequence,相比之下String的實例可以通過compareTo方法進行比較,其他兩個不可以。
19.線程安不安全指什么
線程安全就是說多線程訪問同一代碼,不會產生不確定的結果。編寫線程安全的代碼是低依靠線程同步。
20.Session 與 Token 的區別
session生成方式?
瀏覽器第一次訪問服務器,服務器會創建一個session,然后同時為該session生成一個唯一的會話的key,也就是sessionid,然后,將sessionid及對應的session分別作為key和value保存到緩存中,也可以持久化到數據庫中,然后服務器再把sessionid,以cookie的形式發送給客戶端。這樣瀏覽器下次再訪問時,會直接帶著cookie中的sessionid。然后服務器根據sessionid找到對應的session進行匹配;
還有一種是瀏覽器禁用了cookie或不支持cookie,這種可以通過URL重寫的方式發到服務器;
簡單來講,用戶訪問的時候說他自己是張三,他騙你怎么辦? 那就在服務器端保存張三的信息,給他一個id,讓他下次用id訪問。
token的生成方式?
答:瀏覽器第一次訪問服務器,根據傳過來的唯一標識userId,服務端會通過一些算法,如常用的HMAC-SHA256算法,然后加一個密鑰,生成一個token,然后通過BASE64編碼一下之后將這個token發送給客戶端;客戶端將token保存起來,下次請求時,帶著token,服務器收到請求后,然后會用相同的算法和密鑰去驗證token,如果通過,執行業務操作,不通過,返回不通過信息;
21.java中四種修飾符的限制范圍
1.public 公共的 可以被所有其他類訪問
2.private 私有的 只可以被自己訪問和修改
3.protected 保護的 可以被自己,子類,同一包下的類可以訪問
4.default 默認 同一包中的類可以訪問
22.Object 類中的方法
(1)getclass 返回運行時類
我們寫一段代碼 不運行 會生成.java文件,這就是編譯時類。運行時類是java文件經過編譯變成.class文件,這些文件不能直接運行,交給JVM來解析運行。
(2)hashCode方法
該方法用于哈希查找,重寫了equals方法一般都要重寫hashCode方法。這個方法在一些具有哈希功能的Collection中用到。
一般必須滿足obj1.equals(obj2) = =true。可以推出obj1.hash- Code()= =obj2.hashCode(),但是hashCode相等不一定就滿足equals。不過為了提高效率,應該盡量使上面兩個條件接近等價。
(3)equals 比較地址是否相同 相當于==
重寫equals方法
(4)clone 返回當前對象的副本
克隆分為深克隆和淺克隆
對于一個類只有基本類型,那深克隆和淺克隆是一樣的。如果有引用類型,則不同。
- 深克隆 :新開辟內存空間,值拷貝
- 淺克隆:拷貝的是引用
(5)toString
返回對象的字符串表示形式
線程安全就是說多線程訪問同一代碼,不會產生不確定的結果。編寫線程安全的代碼是低依靠線程同步。
(6)finalize方法
該方法用于釋放資源。因為無法確定該方法什么時候被調用,很少使用。
(7)wait方法
wait方法就是使當前線程等待該對象的鎖,當前線程必須是該對象的擁有者,也就是具有該對象的鎖。wait()方法一直等待,直到獲得鎖或者被中斷。wait(long timeout)設定一個超時間隔,如果在規定時間內沒有獲得鎖就返回。
調用該方法后當前線程進入睡眠狀態,直到以下事件發生。
- 其他線程調用了該對象的notify方法。
- 其他線程調用了該對象的notifyAll方法。
- 其他線程調用了interrupt中斷該線程。
- 時間間隔到了。
此時該線程就可以被調度了,如果是被中斷的話就拋出一個InterruptedException異常。
(8)notify方法
該方法喚醒在該對象上等待的某個線程。
(9)notifyAll方法
該方法喚醒在該對象上等待的所有線程。
23.線程如何通信(面試常問)
方式一:使用 volatile 關鍵字
基于 volatile 關鍵字來實現線程間相互通信是使用共享內存的思想,大致意思就是多個線程同時監聽一個變量,當這個變量發生變化的時候 ,線程能夠感知并執行相應的業務。這也是最簡單的一種實現方式
方式二:使用Object類的wait() 和 notify() 方法
眾所周知,Object類提供了線程間通信的方法:wait()、notify()、notifyaAl(),它們是多線程通信的基礎,而這種實現方式的思想自然是線程間通信。
方式三:使用JUC工具類 CountDownLatch
jdk1.5之后在java.util.concurrent包下提供了很多并發編程相關的工具類,簡化了我們的并發編程代碼的書寫,***CountDownLatch***基于AQS框架,相當于也是維護了一個線程間共享變量state
方式四:使用 ReentrantLock 結合 Condition
方式五:基于LockSupport實現線程間的阻塞和喚醒
24.do while 和while的區別
while和do…while語句都是循環語句,功能都差不多,唯一的區別在于檢驗條件的時間上。while語句在進入循環體之前要先判斷條件是否成立,如果成立的話則進入循環體。
而do…while語句則相反,是先執行循環體,然后再判斷條件是否成立,如果成立的話則繼續循環體,如果不成立則跳出循環,也就是說對于do…while語句,不管條件是否成立都要先執行一遍。
25.Continue和Break區別
break:while循環break是用于永久終止循環。即不執行本次循環中break后面的語句,直接跳出循環。
continue:while循環continue是用于終止本次循環。即本次循環中continue后面的代碼不執行,進行下一次循環的入口判斷。
26. 面向對象的特征
面向對象的編程語言有封裝、繼承 、抽象、多態等4個主要的特征。
封裝: 把描述一個對象的屬性和行為的代碼封裝在一個模塊中,也就是一個類中,屬性用變量定義,行為用方法進行定義,方法可以直接訪問同一個對象中的屬性。
抽象: 把現實生活中的對象抽象為類。分為過程抽象和數據抽象 數據抽象 -->鳥有翅膀,羽毛等(類的屬性) 過程抽象 鳥會飛,會叫(類的方法)
繼承:子類繼承父類的特征和行為。子類可以有父類的方法,屬性(非private)。子類也可以對父類進行擴展,也可以重寫父類的方法。缺點就是提高代碼之間的耦合性。
多態:多態是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時并不確定,而是在程序運行期間才確定(比如:向上轉型,只有運行才能確定其對象屬性)。方法覆蓋和重載體現了多態性。
27.Java創建對象有幾種方式?
java中提供了以下四種創建對象的方式:
28. Java 中 IO 流分為幾種?
按功能來分:輸入流(input)、輸出流(output)。
按類型來分:字節流和字符流。
字節流和字符流的區別是:字節流按 8 位傳輸以字節為單位輸入輸出數據,字符流按 16 位傳輸以字符為單位輸入輸出數據。
29.BIO、NIO、AIO 有什么區別?
BIO:Block IO 同步阻塞式 IO,就是我們平常使用的傳統 IO,它的特點是模式簡單使用方便,并發處理能力低。
NIO:Non IO 同步非阻塞 IO,是傳統 IO 的升級,客戶端和服務器端通過 Channel(通道)通訊,實現了多路復用。
AIO:Asynchronous IO 是 NIO 的升級,也叫 NIO2,實現了異步非堵塞 IO ,異步 IO 的操作基于事件和回調機制。
計算機網絡
1.TCP三次握手,四次揮手
具體答案參考之前博客https://blog.csdn.net/JiaMing11_27/article/details/119651072?spm=1001.2014.3001.5501
2.TCP和UDP區別以及長、短連接
具體答案參考之前博客https://blog.csdn.net/JiaMing11_27/article/details/119651846?spm=1001.2014.3001.5501
3.OSI七層模型和TCP/IP四層協議
4.HTTP常見狀態碼
答案看我之前博客https://blog.csdn.net/JiaMing11_27/article/details/118436439?spm=1001.2014.3001.5501
5.進程三種狀態
進程:進程(Process)是計算機中的程序關于某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位。
進程狀態:
一般來說,進程有三個狀態,即就緒狀態,運行狀態,阻塞狀態
6.進程和線程,進程可以沒有線程嗎
程序至少有一個進程,進程至少有一個線程
線程是進程中執行運算的最小單位,是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。一個線程可以創建和撤消另一個線程,同一進程中的多個線程之間可以并發執行。
7.從輸入URL到頁面展示的詳細過程
1、輸入網址
2、DNS解析
3、建立tcp連接
4、客戶端發送HTTP請求
5、服務器處理請求
6、服務器響應請求
7、瀏覽器展示HTML
8、瀏覽器發送請求獲取其他在HTML中的資源。
JVM
g1 和 cms 區別
吞吐量優先和響應優先的垃圾收集器選擇。
Cms是以獲取最短回收停頓時間為目標的收集器。基于標記-清除算法實現。比較占用cpu資源,切易造成碎片。
G1是面向服務端的垃圾收集器,是jdk9默認的收集器,基于標記-整理算法實現。可利用多核、多cpu,保留分代,實現可預測停頓,可控。
JVM內存模型以及GC算法
參考之前博客:https://blog.csdn.net/JiaMing11_27/article/details/119044707?spm=1001.2014.3001.5501
數據庫(MySql、Redis)
1.數據庫三種刪除方式及其區別
1. 使用delete 語句
特點:
-
delete 屬于數據庫操縱語言DML,表示刪除表中的數據,刪除過程是每次從表中刪除一行,并把該行刪除操作作為事務記錄在日志中保存
-
可以配合事件(transaction)和 回滾(rollback)找回數據,且自增不會被重置
-
delete 既可以對table也可以對view
-
可以全部刪除,也可以按條件刪除
2. 使用truncate 語句
特點:
- truncate 屬于數據庫定義語言DDL,表示刪除表中所有數據,DDL操作是隱性提交的!不能rollback
- truncate一次性的從表中刪除所有數據,不會保存到日志中,相當于直接刪除整個表,再重新創建一個一模一樣的表
- 使用truncate 刪除的數據不能恢復
- truncate 只能對table,執行速度快
3.使用drop語句
特點:
- drop 屬于數據庫定義語言DDL,表示刪除表, 也可以用來刪除數據庫
2.事務的隔離級別
多個事務之間隔離的,相互獨立的。但是如果多個事務操作同一批數據,則會引發一些問題,設置不同的隔離級別就可以解決這些問題*存在問題:
1.臟讀:一個事務,讀取到另一個事務中沒有提交的數據
2.不可重復讀(虛讀):在同一個事務中,兩次讀取到的數據不一樣。
3,幻讀:一個事務操作(DNL)數據表中所有記錄,另一個事務添加了一條數據,則第一個事務查詢不到自己的修改。
隔離級別:
*產生的問題:臟讀、不可重復讀、幻讀2. read committed :讀已提交(oracle)*產生的問題:不可重復讀、幻讀
*可以解決所有的問題
*注意:隔離級別從小到大安全性越來越高,但是效率越來越低
教據庫查詢隔離級別:
select @@tx_isolation;
數據庫設置隔離級別:
set global transaction isolation level級別字符串;
3.MYSQL的兩種存儲引擎區別(事務、鎖級別等等),各自的適用場景
| MYISAM | 不支持外鍵,表鎖,插入數據時,鎖定整個表,查表總行數時,不需要全表掃描 |
| INNODB | 支持外鍵,行鎖,查表總行數時,全表掃描 |
4.索引的好處以及適合使用的場景
索引最大的好處是提高查詢速度,
缺點是更新數據時效率低,因為要同時更新索引
對數據進行頻繁查詢進建立索引,如果要頻繁更改數據不建議使用索引。
5.最左匹配原則
最左匹配原則是針對索引的
舉例來說:兩個字段(name,age)建立聯合索引,如果where age=12這樣的話,是沒有利用到索引的,
這里我們可以簡單的理解為先是對name字段的值排序,然后對age的數據排序,如果直接查age的話,這時就沒有利用到索引了,
查詢條件where name=‘xxx’ and age=xx 這時的話,就利用到索引了,再來思考下where age=xx and name=’xxx‘ 這個sql會利用索引嗎,
按照正常的原則來講是不會利用到的,但是優化器會進行優化,把位置交換下。這個sql也能利用到索引了
6.死鎖怎么解決
找到進程號,kill掉即可!
7.limit分頁
limit 【索引】【一頁多少條數據】
例如: #第二頁 每頁3條數據 limit 3 38. 分組查詢,聚合函數
group by+字段 實現按字段分組查詢
聚合函數有 count,min,max,average 等等
9. where和having區別
where:
- where是一個約束聲明,使用where來約束來自數據庫的數據;
- where是在結果返回之前起作用的;
- where中不能使用聚合函數。
having:
- having是一個過濾聲明;
- 在查詢返回結果集以后,對查詢結果進行的過濾操作;
- 在having中可以使用聚合函數。
10.有哪些數據庫優化方式(重點)
推薦一篇文章,寫的很好!
https://www.zhihu.com/question/36431635
11.索引
索引(Index)是幫助 MySQL 高效獲取數據的數據結構。 常見的查詢算法,順序查找,二分查找,二叉排序樹查找,哈希散列法,分塊查找,平衡多路搜索樹 B 樹(B-tree ),索引是對數據庫表中一個或多個列的值進行排序的結構,建立索引有助于快速獲取信息。
mysql 有4種不同的索引:
- 主鍵索引(PRIMARY)
- 唯一索引(UNIQUE)
- 普通索引(INDEX)
- 全文索引(FULLTEXT)
索引并非是越多越好,創建索引也需要耗費資源,一是增加了數據庫的存儲空間,二是在插入和刪除時要花費較多的時間維護索引
索引加快數據庫的檢索速度索引降低了插入、刪除、修改等維護任務的速度唯一索引可以確保每一行數據的唯一性通過使用索引,可以在查詢的過程中使用優化隱藏器,提高系統的性能索引需要占物理和數據空間
12.數據庫的三范式是什么(重要)
第一范式:列不可再分
第二范式:行可以唯一區分,主鍵約束
第三范式:表的非主屬性不能依賴與其他表的非主屬性 外鍵約束且三大范式是一級一級依賴的,第二范式建立在第一范式上,第三范式建立第一第二范式上 。
13.SQL優化
1、查詢語句中不要使用select *
2、盡量減少子查詢,使用關聯查詢(left join,right join,inner join)替代
3、減少使用IN或者NOT IN ,使用exists,not exists或者關聯查詢語句替代
4、or 的查詢盡量用 union或者union all 代替(在確認沒有重復數據或者不用剔除重復數據時,union all會更好)
5、應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
6、應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如: select id from t where num is null 可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢: select id from t where num=0
14.什么是內聯接、左外聯接、右外聯接?
內聯接(Inner Join):匹配2張表中相關聯的記錄。
左外聯接(Left Outer Join):除了匹配2張表中相關聯的記錄外,還會匹配左表中剩余的記錄,右表中未匹配到的字段用NULL表示。
右外聯接(Right Outer Join):除了匹配2張表中相關聯的記錄外,還會匹配右表中剩余的記錄,左表中未匹配到的字段用NULL表示。在判定左表和右表時,要根據表名出現在Outer Join的左右位置關系
數據結構
數組和鏈表區別,單鏈表和雙鏈表
數組靜態分配內存,鏈表動態分配內存;數組在內存中連續,鏈表不連續;數組利用下標定位,時間復雜度為O(1),鏈表定位元素時間復雜度O(n);數組插入或刪除元素的時間復雜度O(n),鏈表的時間復雜度O(1)。
數組優點:
隨機訪問性強(通過下標進行快速定位)
查找速度快
數組缺點:
插入和刪除效率低(插入和刪除需要移動數據)
可能浪費內存(因為是連續的,所以每次申請數組之前必須規定數組的大小,如果大小不合理,則可能會浪費內存)
內存空間要求高,必須有足夠的連續內存空間。
數組大小固定,不能動態拓展
鏈表的優點:
插入刪除速度快(因為有next指針指向其下一個節點,通過改變指針的指向可以方便的增加刪除元素)
內存利用率高,不會浪費內存(可以使用內存中細小的不連續空間(大于node節點的大小),并且在需要空間的時候才創建空間)
大小沒有固定,拓展很靈活。
鏈表的缺點:
不能隨機查找,必須從第一個開始遍歷,查找效率低
單鏈表:
雙鏈表:
為什么市場上單鏈表的使用多于雙鏈表呢?
從存儲結構來看,每個雙鏈表的節點要比單鏈表的節點多一個指針,而長度為n就需要
n*length(這個指針的length在32位系統中是4字節,在64位系統中是8個字節)
的空間,這在一些追求時間效率不高應用下并不適應,因為它占用空間大于單鏈表所占用的空間;這時設計者就會采用以時間換空間的做法,這時一種工程總體上的衡量。
什么是紅黑樹
推薦一篇文章,用圖的方式理解紅黑樹,非常生動形象!
https://blog.csdn.net/qq_36610462/article/details/83277524
版本管理工具(git)
git命令以及分區
參考我之前博客:https://blog.csdn.net/JiaMing11_27/article/details/119141032?spm=1001.2014.3001.5501
框架
1.SpringMVC執行原理
參考博客:https://blog.csdn.net/JiaMing11_27/article/details/116609811?spm=1001.2014.3001.5501
2.SpringBoot自動裝配原理
參考博客:https://blog.csdn.net/JiaMing11_27/article/details/116610872?spm=1001.2014.3001.5501
3.SpringBoot常用注解
1、@SpringBootApplication
包含@Configuration、@EnableAutoConfiguration、@ComponentScan
通常用在主類上。
2、@Repository
用于標注數據訪問組件,即DAO組件。
3、@Service
用于標注業務層組件。
4、@RestController
用于標注控制層組件(如struts中的action),包含@Controller和@ResponseBody
5、@ResponseBody
表示該方法的返回結果直接寫入HTTP response body中
一般在異步獲取數據時使用,在使用@RequestMapping后,返回值通常解析為跳轉路徑,加上@responsebody后返回結果不會被解析
為跳轉路徑,而是直接寫入HTTP response body中。比如異步獲取json數據,加上@responsebody后,會直接返回json數據。
6、@Component
泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行標注。
7、@ComponentScan
組件掃描。相當于,如果掃描到有@Component @Controller @Service等這些注解的類,則把
這些類注冊為bean。
8、@Configuration
指出該類是 Bean 配置的信息源,相當于XML中的,一般加在主類上。
9、@Bean
相當于XML中的,放在方法的上面,而不是類,意思是產生一個bean,并交給spring管理。
10、@EnableAutoConfiguration
讓 Spring Boot 根據應用所聲明的依賴來對 Spring 框架進行自動配置,一般加在主類上。
11、@AutoWired
byType方式。把配置好的Bean拿來用,完成屬性、方法的組裝,它可以對類成員變量、方法及構造函數進行標注,完成自動裝配的工作。
當加上(required=false)時,就算找不到bean也不報錯。
12、@Qualifier
當有多個同一類型的Bean時,可以用@Qualifier(“name”)來指定。與@Autowired配合使用
13、@Resource(name=“name”,type=“type”)
沒有括號內內容的話,默認byName。與@Autowired干類似的事。
14、@RequestMapping
RequestMapping是一個用來處理請求地址映射的注解,可用于類或方法上。用于類上,表示類中的所有響應請求的方法都是以該地址作為父路徑。
4.GET和POST的區別
以上來自W3cSchool
5.threadlocal原理以及內存泄漏怎么解決
ThreadLocal主要為變量在每個線程中都創建了一個副本,那么每個線程可以訪問自己內部的副本變量。一個線程可以儲存多個ThreadLocal的值
key使用軟引用解決了ThreadLocal對象本身的內存泄漏問題,使用remove方法解決了Entry的value的內存泄漏問題。
6.Spring中 bean生命周期
Spring啟動,查找并加載需要被Spring管理的bean,進行Bean的實例化
Bean實例化后對將Bean的引入和值注入到Bean的屬性中
如果Bean實現了BeanNameAware接口的話,Spring將Bean的Id傳遞給setBeanName()方法
如果Bean實現了BeanFactoryAware接口的話,Spring將調用setBeanFactory()方法,將BeanFactory容器實例傳入
如果Bean實現了ApplicationContextAware接口的話,Spring將調用Bean的setApplicationContext()方法,將bean所在應用上下文引用傳入進來。
如果Bean實現了BeanPostProcessor接口,Spring就將調用他們的postProcessBeforeInitialization()方法。
如果Bean 實現了InitializingBean接口,Spring將調用他們的afterPropertiesSet()方法。類似的,如果bean使用init-method聲明了初始化方法,該方法也會被調用
如果Bean 實現了BeanPostProcessor接口,Spring就將調用他們的postProcessAfterInitialization()方法。
此時,Bean已經準備就緒,可以被應用程序使用了。他們將一直駐留在應用上下文中,直到應用上下文被銷毀。
如果bean實現了DisposableBean接口,Spring將調用它的destory()接口方法,同樣,如果bean使用了destory-method 聲明銷毀方法,該方法也會被調用。
7.Mybatis中的 ${} 和 #{}區別與用法
#{} 這種取值是編譯好SQL語句再取值
${} 這種是取值以后再去編譯SQL語句
#{}方式能夠很大程度防止sql注入。
$方式無法防止Sql注入。
KaTeX parse error: Expected 'EOF', got '#' at position 27: …對象,例如傳入表名. 一般能用#?的就別用.
8.什么是Nginx
Nginx是一個http服務器。是一個使用c語言開發的高性能的http服務器及反向代理服務器。Nginx是一款高性能的http
服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器。由俄羅斯的程序設計師IgorSysoev所開發,官方測試nginx能夠支支撐5萬并發鏈接,并且cpu、內存等資源消耗卻非常低,運行非常穩定。
9. Nginx的應用場景
1、 http服務器。Nginx是一個http服務可以獨立提供http服務。可以做網頁靜態服務器。2、 虛擬主機。可以實現在一臺服務器虛擬出多個網站。例如個人網站使用的虛擬主機。3、 反向代理,負載均衡。當網站的訪問量達到一定程度后,單臺服務器不能滿足用戶的請求時,需要用多臺服務器集群可以使用nginx做反向代理。并且多臺服務器可以平均分擔負載,不會因為某臺服務器負載高宕機而某臺服務器閑置的情況。10.什么是 JWT (JSON WEB TOKEN)
為了在網絡應用環境間傳遞聲明而執行的一種基于JSON的開放標準((RFC
7519).該token被設計為緊湊且安全的,特別適用于分布式站點的單點登錄(SSO)場景。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便于從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用于認證,也可被加密。
分為三部分:
- 頭部(header)
- 載荷(payload, 類似于飛機上承載的物品)
- 簽證(signature)
jwt是SpringSucurity框架中的,內容不多,相對來說視頻理解起來更輕松,推薦一個講的很好的課程,可以更好地理解JWT。
https://www.bilibili.com/video/BV1pr4y1F7bC?from=search&seid=8590849621746951843
11.MyBatis 與 Hibernate 有哪些不同?
1、Mybatis 和 hibernate 不同,它不完全是一個 ORM 框架,因為 MyBatis 需要程序員自己編寫 Sql 語句。
2、Mybatis 直接編寫原生態 sql,可以嚴格控制 sql
執行性能,靈活度高,非常適合對關系數據模型要求不高的軟件開發,因為這類軟件需求變化頻繁,一但需求變化要求迅速輸出成果。但是靈活的前提是
mybatis 無法做到數據庫無關性,如果需要實現支持多種數據庫的軟件,則需要自定義多套 sql 映射文件,工作量大。
3、Hibernate 對象/關系映射能力強,數據庫無關性好,對于關系模型要求高的軟件,如果用 hibernate
開發可以節省很多代碼,提高效率。
12.通常一個 Xml 映射文件,都會寫一個 Dao 接口與之對應, 這個 Dao 接口的工作原理是什么?Dao 接口里的方法, 參數不同時,方法能重載嗎?
Dao 接口即 Mapper 接口。接口的全限名,就是映射文件中的 namespace 的值;
接口的方法名,就是映射文件中 Mapper 的 Statement 的 id 值;
接口方法內的參數,就是傳遞給 sql 的參數。
Mapper 接口是沒有實現類的,當調用接口方法時,接口全限名+方法名拼接字符
串作為 key 值,可唯一定位一個 MapperStatement。在 Mybatis 中,每一個
標簽,都會被解析為一個MapperStatement 對象。
舉例:com.mybatis3.mappers.StudentDao.findStudentById,
可以唯一找到 namespace 為 com.mybatis3.mappers.StudentDao 下面 id 為findStudentById 的 MapperStatement。
Mapper 接口里的方法,是不能重載的,因為是使用 全限名+方法名 的保存和尋
找策略。
Mapper 接口的工作原理是 JDK 動態代理,Mybatis 運行時會使用 JDK
動態代理為 Mapper 接口生成代理對象 proxy,代理對象會攔截接口方法,轉而執行 MapperStatement 所代表的 sql,然后將 sql 執行結果返回。
13.Mybatis 的一級、二級緩存
1)一級緩存: 基于 PerpetualCache 的 HashMap 本地緩存,其存儲作用域為Session,當 Session flush 或 close 之后,該 Session 中的所有 Cache 就將清空,默認打開一級緩存。
2)二級緩存與一級緩存其機制相同,默認也是采用 PerpetualCache,HashMap存儲,不同在于其存儲作用域為 Mapper(Namespace),并且可自定義存儲源,如 Ehcache。默認不打開二級緩存,要開啟二級緩存,使用二級緩存屬性類需要實現 Serializable 序列化接口(可用來保存對象的狀態),可在它的映射文件中配置 ;
3)對于緩存數據更新機制,當某一個作用域(一級緩存 Session/二級緩存Namespaces)的進行了 C/U/D 操作后,默認該作用域下所有 select 中的緩存將被 clear。
14.什么是 MyBatis 的接口綁定?有哪些實現方式?
接口綁定,就是在 MyBatis 中任意定義接口,然后把接口里面的方法和 SQL 語句綁定, 我們直接調用接口方法就可以,這樣比起原來了 SqlSession 提供的方法我們可以有更加靈活的選擇和設置。
接口綁定有兩種實現方式:
一種是通過注解綁定,就是在接口的方法上面加上@Select、@Update 等注解,里面包含 Sql 語句來綁定;
另外一種就是通過 xml里面寫 SQL 來綁定, 在這種情況下,要指定 xml 映射文件里面的 namespace 必須為接口的全路徑名。
當 Sql 語句比較簡單時候,用注解綁定, 當 SQL 語句比較復雜時候,用 xml 綁定,一般用 xml 綁定的比較多。
15.Spring Boot 的核心注解是哪個?它主要由哪幾個注解組成的?
啟動類上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要組合包含了以下3 個注解:
@SpringBootConfiguration:組合了 @Configuration 注解,實現配置文件的功能。@EnableAutoConfiguration:打開自動配置的功能,也可以關閉某個自動配置的選項,如關閉數據源自動配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。@ComponentScan:Spring組件掃描
16.什么是 CSRF 攻擊?
CSRF 代表跨站請求偽造。這是一種攻擊,迫使最終用戶在當前通過身份驗證的Web 應用程序上執行不需要的操作。CSRF 攻擊專門針對狀態改變請求,而不是數據竊取,因為攻擊者無法查看對偽造請求的響應。
17.RequestMapping 和 GetMapping 的不同之處在哪里?
RequestMapping 具有類屬性的,可以進行 GET,POST,PUT 或者其它的注釋中具有的請求方法。GetMapping 是 GET 請求方法中的一個特例。
它只是 ResquestMapping 的一個延伸,目的是為了提高清晰度。
消息隊列RabbitMQ
1.什么是 rabbitmq,為什么要使用?
采用 AMQP 高級消息隊列協議的一種消息隊列技術,最大的特點就是消費并不需要確保提供方存在,實現了服務之間的高度解耦。
- 在分布式系統下具備異步,削峰,負載均衡等一系列高級功能;
- 擁有持久化的機制,進程消息,隊列中的信息也可以保存下來。
- 實現消費者和生產者之間的解耦。
- 對于高并發場景下,利用消息隊列可以使得同步訪問變為串行訪問達到一定量的限流,利于數據庫的操作。
- 可以使用消息隊列達到異步下單的效果,排隊中,后臺進行邏輯下單。
2. rabbitmq 的使用場景
- 服務間異步通信
- 順序消費
- 定時任務
- 請求削峰
3.如何避免消息重復投遞或重復消費?
在消息生產時,MQ 內部針對每條生產者發送的消息生成一個 inner-msg-id,作為去重的依據(消息投遞失敗并重傳),避免重復的消息進入隊列;
在消息消費時,要求消息體中必須要有一個 bizId(對于同一業務全局唯一,如支付 ID、訂單 ID、帖子 ID 等)作為去重的依據,避免同一條消息被重復消費。
4.消息基于什么傳輸?
由于 TCP 連接的創建和銷毀開銷較大,且并發數受系統資源限制,會造成性能瓶頸。
RabbitMQ使用信道的方式來傳輸數據。信道是建立在真實的 TCP 連接內的虛擬連接,且每條 TCP 連接上的信道數量沒有限制
5.Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么區別?
對于吞吐量來說kafka和RocketMQ支撐高吞吐,ActiveMQ和RabbitMQ比他們低一個數量級。對于延遲量來說RabbitMQ是最低的。
1.從社區活躍度按照目前網絡上的資料,RabbitMQ 、activeM 、ZeroMQ 三者中,綜合來看,RabbitMQ 是首選。
2.持久化消息比較ActiveMq 和RabbitMq 都支持。持久化消息主要是指我們機器在不可抗力因素等情況下掛掉了,消息不會丟失的機制。
3.綜合技術實現可靠性、靈活的路由、集群、事務、高可用的隊列、消息排序、問題追蹤、可視化管理工具、插件系統等等。RabbitMq / Kafka 最好,ActiveMq 次之,ZeroMq 最差。當然ZeroMq 也可以做到,不過自己必須手動寫代碼實現,代碼量不小。尤其是可靠性中的:持久性、投遞確認、發布者證實和高可用性。
4.高并發毋庸置疑,RabbitMQ 最高,原因是它的實現語言是天生具備高并發高可用的erlang 語言。
5.比較關注的比較, RabbitMQ 和 KafkaRabbitMq 比Kafka 成熟,在可用性上,穩定性上,可靠性上, RabbitMq 勝于 Kafka (理論上)。另外,Kafka 的定位主要在日志等方面, 因為Kafka 設計的初衷就是處理日志的,可以看做是一個日志(消息)系統一個重要組件,針對性很強,所以 如果業務方面還是建議選擇 RabbitMq 。還有就是,Kafka 的性能(吞吐量、TPS )比RabbitMq 要高出來很多
持續更新!!!
時間匆忙,如果有錯誤歡迎指出,有什么缺少的也可以私信我,我會及時補充
創作不易,點個贊再走吧,你的支持是我創作的最大動力,謝謝!
總結
以上是生活随笔為你收集整理的Java面试题附答案(面试必会)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php数组用递归函数求和,如何用php递
- 下一篇: java美元兑换,(Java实现) 美元