以下是 Java 面試高頻 10 道題 + 精煉答案(覆蓋基礎核心、JVM、併發、集合等重點,適合面試快速記憶):
1. 談談 Java 的三大特性(封裝、繼承、多態)
- 封裝:隱藏對象內部實現細節,通過
private限制訪問,提供getter/setter等公共方法交互,降低耦合、提高安全性(比如實體類的屬性封裝)。 - 繼承:子類通過
extends繼承父類非私有屬性和方法,實現代碼複用;但 Java 只支持單繼承(避免菱形依賴),可通過接口間接實現多繼承。 - 多態:同一行為的不同表現形式,核心是「方法重寫(子類覆寫父類方法)」和「向上轉型(父類引用指向子類對象)」,比如
List list = new ArrayList<>(),調用list.add()時實際執行 ArrayList 的實現,提高代碼靈活性。
2. String、StringBuffer、StringBuilder 的區別
|
特性
|
String
|
StringBuffer
|
StringBuilder
|
|
可變性
|
不可變(final 修飾字符數組)
|
可變(數組擴容)
|
可變(數組擴容)
|
|
線程安全
|
安全(無修改操作)
|
安全(方法加 |
不安全(無鎖)
|
|
效率
|
最低(修改會創建新對象)
|
中等
|
最高
|
|
適用場景
|
少量字符串操作
|
多線程環境字符串拼接
|
單線程環境字符串拼接
|
3. 什麼是 JVM 內存模型?主要分區有哪些?
JVM 內存模型(JMM)定義了線程如何通過內存交互,解決多線程可見性、原子性、有序性問題; 核心分區(基於 HotSpot 虛擬機):
- 程序計數器:線程私有,記錄當前線程執行的字節碼行號,無 OOM 可能。
- 虛擬機棧:線程私有,存儲方法調用的棧幀(局部變量、操作數棧等),棧深度溢出會拋
StackOverflowError,擴容失敗拋OutOfMemoryError。 - 本地方法棧:線程私有,為 Native 方法(如
System.currentTimeMillis())提供內存支持,同樣可能拋 StackOverflowError/OOM。 - 堆:線程共享,存儲對象實例和數組,是 GC 主要區域(分年輕代、老年代),OOM 高頻發生區。
- 方法區:線程共享,存儲類信息、常量、靜態變量等(JDK 8 後用元空間 Metaspace 實現,佔用本地內存,默認無上限)。
4. 什麼是 GC(垃圾回收)?常見 GC 算法和收集器有哪些?
- GC 定義:自動回收堆中“不可達對象”(無引用指向的對象)的內存,避免內存泄漏,無需手動釋放。
- 核心算法:
- 標記-清除:先標記垃圾,再清除,效率低、會產生內存碎片。
- 複製算法:將內存分為兩塊,存活對象複製到另一塊,清除原塊,無碎片、效率高(年輕代默認用)。
- 標記-整理:標記後將存活對象向一端移動,再清除剩餘區域(老年代默認用)。
- 常見收集器:
- 年輕代:SerialGC(串行,單線程)、Parallel Scavenge(並行,注重吞吐量)。
- 老年代:Serial Old(串行)、Parallel Old(並行)、CMS(併發,注重響應時間)、G1(區域分代,兼顧吞吐量和響應時間)。
5. Java 中實現多線程的三種方式及區別
- 方式 1:繼承 Thread 類:重寫
run()方法,調用start()啓動線程(底層調用start0()native 方法)。 缺點:單繼承限制,無法繼承其他類。 - 方式 2:實現 Runnable 接口:實現
run()方法,通過new Thread(runnable).start()啓動。 優點:無繼承限制,可實現多個接口;缺點:無法直接獲取返回值。 - 方式 3:實現 Callable 接口:實現
call()方法(可返回值、拋異常),結合FutureTask包裝,通過線程池啓動。 優點:支持返回值和異常處理,適合異步任務;缺點:代碼稍複雜。
6. 什麼是線程安全?如何保證線程安全?
- 線程安全:多線程併發訪問共享資源時,不會出現數據錯亂、死鎖等問題(比如多線程搶票,不會出現超賣、重複售票)。
- 實現方式:
- 鎖機制:
synchronized(關鍵字,可修飾方法/代碼塊,底層是監視器鎖)、ReentrantLock(類鎖,支持公平鎖/非公平鎖、可中斷)。 - 無鎖機制:
volatile(修飾變量,保證可見性和有序性,不保證原子性)、原子類(AtomicInteger,基於 CAS 實現原子操作)。 - 線程封閉:局部變量(線程私有,無共享)、ThreadLocal(每個線程獨立存儲副本,避免共享)。
- 併發容器:
ConcurrentHashMap(分段鎖/CAS 實現線程安全)、CopyOnWriteArrayList(寫時複製,讀無鎖)。
7. HashMap 和 ConcurrentHashMap 的區別(JDK 8+)
|
特性
|
HashMap
|
ConcurrentHashMap
|
|
線程安全
|
不安全(多線程put可能擴容死循環、數據丟失)
|
安全
|
|
實現方式
|
數組+鏈表/紅黑樹(鏈表長度>8轉紅黑樹)
|
數組+鏈表/紅黑樹+CAS+synchronized(分段鎖優化為節點鎖)
|
|
支持操作
|
無原子操作,需手動加鎖
|
支持 |
|
遍歷特性
|
快速失敗(modCount校驗,併發修改拋 ConcurrentModificationException)
|
弱一致性(遍歷不拋異常,可能讀取舊數據)
|
|
適用場景
|
單線程環境
|
多線程併發環境
|
8. 什麼是異常體系?Checked Exception 和 Unchecked Exception 的區別
- 異常體系:頂層是
Throwable,分為Error(錯誤,如OutOfMemoryError,JVM 層面,無法捕獲修復)和Exception(異常,可處理)。 - Checked Exception(受檢異常):編譯期強制檢查,必須捕獲或聲明拋出(如
IOException、SQLException),避免遺漏處理。 - Unchecked Exception(非受檢異常):編譯期不檢查,繼承自
RuntimeException(如NullPointerException、ArrayIndexOutOfBoundsException),通常是代碼邏輯錯誤,無需強制捕獲,建議通過代碼優化避免。
9. 談談你對 Spring IoC 和 AOP 的理解
- IoC(控制反轉):
- 核心:將對象的創建、依賴注入交給 Spring 容器管理,而非手動
new對象,降低組件耦合。 - 實現:通過 XML 配置、註解(
@Component、@Autowired)或 Java 配置類定義 Bean,容器啓動時初始化 Bean 並注入依賴。 - 好處:解耦、便於測試(可替換依賴的模擬對象)、提高代碼複用。
- AOP(面向切面編程):
- 核心:在不修改原有代碼的前提下,對方法進行增強(如日誌、事務、權限校驗),將通用邏輯抽離為“切面”。
- 關鍵概念:切點(Pointcut,指定增強的方法)、通知(Advice,增強的邏輯,如
@Before、@AfterReturning)、切面(Aspect,切點+通知)、動態代理(JDK 動態代理基於接口,CGLIB 基於子類,Spring 自動選擇)。 - 應用:Spring 事務管理(
@Transactional)、全局日誌打印、接口權限攔截。
10. 什麼是分佈式事務?常見解決方案有哪些?
- 分佈式事務:跨多個服務/數據庫的事務(如下單流程:扣庫存、減餘額、創建訂單分屬不同服務),需保證“所有操作成功或所有失敗”,滿足 ACID 特性。
- 常見解決方案:
- 2PC(兩階段提交):分為準備階段(所有參與者確認可提交)和提交階段(協調者通知提交),缺點是阻塞、協調者單點故障。
- TCC(Try-Confirm-Cancel):業務層實現 Try(資源檢查預留)、Confirm(確認提交)、Cancel(回滾釋放),無鎖、高性能,缺點是代碼侵入性強。
- 本地消息表+MQ:本地事務和消息表原子提交,通過 MQ 異步通知其他服務,失敗則重試,適合最終一致性場景(如訂單通知)。
- Saga 模式:將分佈式事務拆分為多個本地事務,每個事務失敗時執行補償操作,適合長事務(如物流履約)。
- 事務消息(RocketMQ 支持):MQ 保證消息可靠投遞,接收方確認後才提交本地事務,簡化一致性實現。
這些題目覆蓋了 Java 基礎、JVM、併發、集合、Spring 框架、分佈式核心考點,答案簡潔且直擊要點,面試時可結合實際項目經驗補充案例(比如“項目中用 ConcurrentHashMap 解決了多線程統計問題”),效果更好。