《隔離十四天》系列 -第十一天 -Java面試題大全

前言

今天又是朝氣蓬勃的一天,雖然還沒找到合適的工作,但是也不能喪失了對生活的信心,還是要勇敢的面對生活,比如我們說一句,奧裏給!!!

當然了每日膜拜大佬的節奏不能斷了,還是要在網上多跟各位大佬學習,學習技術,提高自己。
在這裏插入圖片描述

好了,言歸正傳,今天依然是看面試題的一天,當然也學習了基礎薄弱的數據結構,果真發覺自己啥都不懂,不配說自己是軟件工程出身的。
在這裏插入圖片描述

這些面試題是自己在網上看面試題的時候看到覺得自己不懂的然後copy到筆記中的,自己是個面試題的搬運工。
在這裏插入圖片描述

說一下 HashMap 的實現原理?

HashMap 基於 Hash 算法實現的,我們通過 put(key,value)存儲,get(key)來獲取。當傳入 key 時,HashMap 會根據
 key. hashCode() 計算出 hash 值,根據 hash 值將 value 保存在 bucket 裏。當計算出的 hash 值相同時,我們稱
 之爲 hash 衝突,HashMap 的做法是用鏈表和紅黑樹存儲相同 hash 值的 value。當 hash 衝突的個數比較少時,使用
 鏈表否則使用紅黑樹。

說一下 HashSet 的實現原理?

HashSet 是基於 HashMap 實現的,HashSet 底層使用 HashMap 來保存所有元素,因此 HashSet 的實現比較簡單,相關
 HashSet 的操作,基本上都是直接調用底層 HashMap 的相關方法來完成,HashSet 不允許重複的值。

ArrayList 和 LinkedList 的區別是什麼?

數據結構實現:ArrayList 是動態數組的數據結構實現,而 LinkedList 是雙向鏈表的數據結構實現。
	
隨機訪問效率:ArrayList 比 LinkedList 在隨機訪問的時候效率要高,因爲 LinkedList 是線性的數據存儲方式,所以
需要移動指針從前往後依次查找。
	
增加和刪除效率:在非首尾的增加和刪除操作,LinkedList 要比 ArrayList 效率要高,因爲 ArrayList 增刪操作要影
響數組內的其他數據的下標。

綜合來說,在需要頻繁讀取集合中的元素時,更推薦使用 ArrayList,而在插入和刪除操作較多時,更推薦使用LinkedList。

接口和抽象類有什麼區別?

實現:抽象類的子類使用 extends 來繼承;接口必須使用 implements 來實現接口。
	
構造函數:抽象類可以有構造函數;接口不能有。
	
實現數量:類可以實現很多個接口;但是隻能繼承一個抽象類。
 
訪問修飾符:接口中的方法默認使用 public 修飾;抽象類中的方法可以是任意訪問修飾符。

抽象類能使用 final 修飾嗎?
不能,定義抽象類就是讓其他類繼承的,如果定義爲 final 該類就不能被繼承,這樣彼此就會產生矛盾,所以 final 不能
修飾抽象類,
final 在 Java 中有什麼作用?
	
final 修飾的類叫最終類,該類不能被繼承。
	
final 修飾的方法不能被重寫。
	
final 修飾的變量叫常量,常量必須初始化,初始化之後值就不能被修改。

抽象類必須要有抽象方法嗎?
不需要,抽象類不一定非要有抽象方法。但是有抽象方法的一定是抽象類

如何將字符串反轉?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba

Java 中操作字符串都有哪些類?它們之間有什麼區別?

操作字符串的類有:String、StringBuffer、StringBuilder。
String 和 StringBuffer、StringBuilder 的區別在於 String 聲明的是不可變的對象,每次操作都會生成新的String
 對象,然後將指針指向新的 String 對象,而 StringBuffer、StringBuilder 可以在原有對象的基礎上進行操作,所以
 在經常改變字符串內容的情況下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的區別在於,StringBuffer 是線程安全的,而 StringBuilder 是非線程安全
的,但 StringBuilder 的性能卻高於 StringBuffer,所以在單線程環境下推薦使用 StringBuilder,多線程環境下推
薦使用 StringBuffer。

HashMap 和 Hashtable 有什麼區別?

存儲:HashMap 運行 key 和 value 爲 null,而 Hashtable 不允許。
	
線程安全:Hashtable 是線程安全的,而 HashMap 是非線程安全的。
	
推薦使用:在 Hashtable 的類註釋可以看到,Hashtable 是保留類不建議使用,推薦在單線程環境下使用 HashMap 替代
,如果需要多線程使用則用 ConcurrentHashMap 替代。

在 Queue 中 poll()和 remove()有什麼區別?

相同點:都是返回第一個元素,並在隊列中刪除返回的對象。
	
不同點:如果沒有元素 poll()會返回 null,而 remove()會直接拋出 NoSuchElementException 異常。

創建線程有哪幾種方式?

創建線程有三種方式:
	
繼承 Thread 重寫 run 方法;
	
實現 Runnable 接口;
	
實現 Callable 接口。

線程有哪些狀態?

線程的狀態:
NEW 尚未啓動

RUNNABLE 正在執行中
	
BLOCKED 阻塞的(被同步鎖或者IO鎖阻塞)
 
WAITING 永久等待狀態
	
TIMED_WAITING 等待指定的時間重新被喚醒的狀態
	
TERMINATED 執行完成

sleep() 和 wait() 有什麼區別?

* 
類的不同:sleep() 來自 Thread,wait() 來自 Object。
	
釋放鎖:sleep() 不釋放鎖;wait() 釋放鎖。
	
用法不同:sleep() 時間到會自動恢復;wait() 可以使用 notify()/notifyAll()直接喚醒。

線程的 run() 和 start() 有什麼區別?

start() 方法用於啓動線程,run() 方法用於執行線程的運行時代碼。run() 可以重複調用,而 start() 只能調用一次。

怎麼防止死鎖?

儘量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),設置超時
時間,超時可以退出防止死鎖。
	
儘量使用 Java. util. concurrent 併發類代替自己手寫鎖。
	
儘量降低鎖的使用粒度,儘量不要幾個功能用同一把鎖。
	
儘量減少同步的代碼塊。

synchronized 和 Lock 有什麼區別?

synchronized 可以給類、方法、代碼塊加鎖;而 lock 只能給代碼塊加鎖。
	
synchronized 不需要手動獲取鎖和釋放鎖,使用簡單,發生異常會自動釋放鎖,不會造成死鎖;而 lock 需要自己加鎖和
釋放鎖,如果使用不當沒有 unLock()去釋放鎖就會造成死鎖。
	
通過 Lock 可以知道有沒有成功獲取鎖,而 synchronized 卻無法辦到。

synchronized 和 ReentrantLock 區別是什麼?

synchronized 早期的實現比較低效,對比 ReentrantLock,大多數場景性能都相差較大,但是在 Java 6 中對 
synchronized 進行了非常多的改進。
主要區別如下:
	
ReentrantLock 使用起來比較靈活,但是必須有釋放鎖的配合動作;
	
ReentrantLock 必須手動獲取與釋放鎖,而 synchronized 不需要手動釋放和開啓鎖;
	
ReentrantLock 只適用於代碼塊鎖,而 synchronized 可用於修飾方法、代碼塊等。

什麼是反射?

反射是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一
個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲 Java 語言的反射機制。

什麼是 Java 序列化?什麼情況下需要序列化?

Java 序列化是爲了保存各種對象在內存中的狀態,並且可以把保存的對象狀態再讀出來。
以下情況需要使用 Java 序列化:
	
想把的內存中的對象狀態保存到一個文件中或者數據庫中時候;
	
想用套接字在網絡上傳送對象的時候;
	
想通過RMI(遠程方法調用)傳輸對象的時候。

session 和 cookie 有什麼區別?

	
存儲位置不同:session 存儲在服務器端;cookie 存儲在瀏覽器端。
	
安全性不同:cookie 安全性一般,在瀏覽器存儲,可以被僞造和修改。
	
容量和個數限制:cookie 有容量限制,每個站點下的 cookie 也有個數限制。
	
存儲的多樣性:session 可以存儲在 Redis 中、數據庫中、應用程序中;而 cookie 只能存儲在瀏覽器中。

說一下 session 的工作原理?

session 的工作原理是客戶端登錄完成之後,服務器會創建對應的 session,session 創建完之後,會把 session 的 
id 發送給客戶端,客戶端再存儲到瀏覽器中。這樣客戶端每次訪問服務器時,都會帶着 sessionid,
服務器拿到 sessionid 之後,在內存找到與之對應的 session 這樣就可以正常工作了。

如果客戶端禁止 cookie 能實現 session 還能用嗎?
可以用,session 只是依賴 cookie 存儲 sessionid,如果 cookie 被禁用了,可以使用 url 中添加 sessionid 的方
式保證 session 能正常使用。

final、finally、finalize 有什麼區別?

	
final:是修飾符,如果修飾類,此類不能被繼承;如果修飾方法和變量,則表示此方法和此變量不能在被改變,只能使用。
	
finally:是 try{} catch{} finally{} 最後一部分,表示不論發生任何情況都會執行,finally 部分可以省略,但如果
 finally 部分存在,則一定會執行 finally 裏面的代碼。
	
finalize: 是 Object 類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法。

簡述 tcp 和 udp的區別?

tcp 和 udp 是 OSI 模型中的運輸層中的協議。tcp 提供可靠的通信傳輸,而 udp 則常被用於讓廣播和細節控制交給應用的通信傳輸。
兩者的區別大致如下:
	
tcp 面向連接,udp 面向非連接即發送數據前不需要建立鏈接;
	
tcp 提供可靠的服務(數據傳輸),udp 無法保證;
	
tcp 面向字節流,udp 面向報文;
	
tcp 數據傳輸慢,udp 數據傳輸快;

如何實現跨域?

實現跨域有以下幾種方案:
	
服務器端運行跨域 設置 CORS 等於 *;
	
在單個接口使用註解 @CrossOrigin 運行跨域;
	
使用 jsonp 跨域;

說一下你熟悉的設計模式?

	
單例模式:保證被創建一次,節省系統開銷。
	
工廠模式(簡單工廠、抽象工廠):解耦代碼。
	
觀察者模式:定義了對象之間的一對多的依賴,這樣一來,當一個對象改變時,它的所有的依賴者都會收到通知並自動更新。
	
外觀模式:提供一個統一的接口,用來訪問子系統中的一羣接口,外觀定義了一個高層的接口,讓子系統更容易使用。
	
模版方法模式:定義了一個算法的骨架,而將一些步驟延遲到子類中,模版方法使得子類可以在不改變算法結構的情況下,
重新定義算法的步驟。
	
狀態模式:允許對象在內部狀態改變時改變它的行爲,對象看起來好像修改了它的類。

spring 事務實現方式有哪些?

	
聲明式事務:聲明式事務也有兩種實現方式,基於 xml 配置文件的方式和註解方式(在類上添加 @Transaction 註解)。
	
編碼方式:提供編碼的形式管理和維護事務。

爲什麼要用 spring boot?

	
配置簡單
	
獨立運行
	
自動裝配
	
無代碼生成和 xml 配置
	
提供應用監控
	
提升開發效率

spring cloud 斷路器的作用是什麼?

在分佈式架構中,斷路器模式的作用也是類似的,當某個服務單元發生故障(類似用電器發生短路)之後,通過斷路器的故
障監控(類似熔斷保險絲),向調用方返回一個錯誤響應,而不是長時間的等待。這樣就不會使得線程因調用故障服務被長
時間佔用不釋放,避免了故障在分佈式系統中的蔓延。

spring cloud 的核心組件有哪些?

	
Eureka:服務註冊於發現。
	
Feign:基於動態代理機制,根據註解和選擇的機器,拼接請求 url 地址,發起請求。
	
Ribbon:實現負載均衡,從一個服務的多臺機器中選擇一臺。
	
Hystrix:提供線程池,不同的服務走不同的線程池,實現了不同服務調用的隔離,避免了服務雪崩的問題。
	
Zuul:網關管理,由 Zuul 網關轉發請求給對應的服務。

MyBatis 是否支持延遲加載?延遲加載的原理是什麼?

MyBatis 支持延遲加載,設置 lazyLoadingEnabled=true 即可。
延遲加載的原理的是調用的時候觸發加載,而不是在初始化的時候就加載信息。比如調用 a. getB(). getName(),這個時候發現 a. getB()
 的值爲 null,此時會單獨觸發事先保存好的關聯 B 對象的 SQL,先查詢出來 B,然後再調用 a. setB(b),而這時候再調用 
 a. getB(). getName() 就有值了,這就是延遲加載的基本原理。

以上就是今天搬運的一些面試題了,希望對大家有用,也祝各位能在這個時候找到一個合適的工作。每天都是努力向上的一天。

最後也希望大佬能夠分享一些面試經驗,萬分感謝。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章