本文匯總 36 道高頻 Java 核心面試題,涵蓋基礎語法、集合框架、併發編程、JVM 內存模型、類加載機制、GC 算法與調優、數據庫、設計模式等全棧知識體系。每題給出標準答案、核心考點、易錯陷阱及實戰建議,適合校招、社招系統性複習與查漏補缺。
答案:
底層原理:三者最終都操作 char[](Java 9+ 為 byte[] + coder),擴容機制為 1.5 倍 + 1。拼接優化:編譯器將 + 優化為 StringBuilder.append(),但循環中拼接仍會重複創建 Builder,需手動提取。
核心區別:
Iterable,子接口 List(有序、可重複)、Set(無序、唯一)、Queue(隊列)static 方法:排序、二分查找、線程安全包裝、空集合、最大最小值等注意:Map 不繼承 Collection,屬於獨立體系(鍵值對)。
| 集合 | 實現方式 | 備註 |
|---|---|---|
| Vector | 方法級 synchronized | 已過時,效率低,推薦 Collections.synchronizedList(new ArrayList<>()) 或 CopyOnWriteArrayList |
| Stack | 繼承 Vector | LIFO,同 Vector 缺點,推薦 Deque (ArrayDeque) |
| Hashtable | 方法級 synchronized | 已過時,Key/Value 不可為 null,推薦 ConcurrentHashMap |
| Enumeration | 迭代器前身 | 已過時,推薦 Iterator |
| ConcurrentHashMap | CAS + synchronized (JDK8) / 分段鎖 (JDK7) | 高併發首選,Key/Value 均不可為 null |
| CopyOnWriteArrayList/Set | 寫時復制 | 讀多寫少場景,迭代器弱一致性 |
定義:多線程訪問同一對象時,無需調用方同步,對象行為正確(符合規範)。
實現層級:
見前文「Java 基礎核心知識體系總結」表格。為什麼需要包裝類:泛型參數只能是引用類型、集合存儲、反射調用、可為 null 表示「無值」語義。
hashCode() + equals() 降級為 int switch,再通過 tableswitch/lookupswitch 指令實現| 維度 | == | equals() |
|---|---|---|
| 類型 | 運算符 | Object 方法 |
| 基本類型 | 比較值 | 不適用 |
| 引用類型 | 比較地址(引用) | 默認比地址,常重寫比內容 |
| null 安全 | 安全 | 需非空判斷或 Objects.equals() |
詳見前文 GC 章節。面試加分點:WeakHashMap 鍵用弱引用,ThreadLocalMap Entry 繼承 WeakReference,Guava Cache 用軟引用實現內存敏感緩存。
Objects.hash(field1, field2...) 或 IDE 生成| 特性 | ArrayList | LinkedList | Vector |
|---|---|---|---|
| 底層結構 | 動態數組 | 雙向鏈表 | 動態數組 |
| 隨機訪問 | O(1) 快 | O(n) 慢 | O(1) |
| 頭尾增刪 | O(n) 需移動 | O(1) 快 | O(n) |
| 線程安全 | 否 | 否 | 是 (synchronized) |
| 擴容機制 | 1.5倍 | 無 | 2倍 |
選型:默認 ArrayList;頻繁頭尾操作用 LinkedList(或 Deque);多線程用 CopyOnWriteArrayList 或同步包裝。
Deque| 維度 | HashMap | Hashtable |
|---|---|---|
| 線程安全 | 否 | 是 (synchronized) |
| Null 支持 | Key/Value 可為 null | 均不可為 null |
| 繼承體系 | AbstractMap → Map | Dictionary → Map |
| 初始容量/擴容 | 16 / 2倍 | 11 / 2n+1 |
| 遍歷方式 | Iterator (fail-fast) | Enumerator + Iterator |
| JDK8 優化 | 鏈表轉紅黑樹 (threshold=8) | 無 |
結論:一定執行(JVM 保證),除非 System.exit()、棧溢出、死循環、殺進程。
返回值規則:
| 異常類型 | 原因 | 排查工具/參數 |
|---|---|---|
| Java heap space | 堆內存不足/洩漏 | -Xmx/-Xms, jmap -histo:live, MAT 分析 heap dump |
| PermGen space (JDK7) | 類加載過多/字符串常量池 | -XX:PermSize/MaxPermSize, -XX:+UseCompressedClassPointers |
| Metaspace (JDK8+) | 類元數據過多 | -XX:MaxMetaspaceSize, jcmd GC.class_histogram |
| StackOverflowError | 遞歸過深/死循環 | -Xss 設置棧大小, jstack 定位調用鏈 |
| Direct buffer memory | NIO 直接內存/Netty 泄漏 | -XX:MaxDirectMemorySize, 監控 DirectBuffer 計數 |
private 字段 + 公共方法super 調用父構造| 維度 | Override (重寫) | Overload (重載) |
|---|---|---|
| 關系 | 父子類 | 同一類內 |
| 方法簽名 | 完全相同 | 名稱相同,參數列表不同 |
| 返回類型 | 兼容 (协变返回类型) | 可不同 |
| 拋出異常 | 子類 ≤ 父類 | 無限制 |
| 多態類型 | 運行時 (動態分派) | 編譯時 (靜態分派) |
| 維度 | Interface | Abstract Class |
|---|---|---|
| 繼承 | 多實現 | 單繼承 |
| 方法 | JDK8 前全 abstract,JDK8+ default/static/private | 可有實現方法 |
| 字段 | 隱式 public static final | 任意修飾符 |
| 構造方法 | 無 | 有 (子類調用) |
| 設計意圖 | 契約/能力定義 | 代碼復用/模板方法 |
OuterClass.this),需外部實例創建,可訪問所有成員invokevirtual 不參與invokevirtual 指令核心邏輯推薦 Runnable/Callable:
| 特性 | synchronized | ReentrantLock |
|---|---|---|
| 類型 | 關鍵字 (JVM 內置) | 類 (AQS 實現) |
| 鎖釋放 | 自動 (塊結束/異常) | 手動 unlock() (finally 中) |
| 可中斷 | 否 | lockInterruptibly() |
| 公平鎖 | 非公平 | 可選 (構造傳 true) |
| 條件變量 | wait/notify (單一) | 多 Condition (newCondition()) |
| 性能 (低爭用) | 優化後極佳 (偏向鎖/輕量級鎖) | 略低 |
| 性能 (高爭用) | 膨脹為重量級鎖 | 穩定優於 synchronized |
synchronized void method() → 鎖 thissynchronized(this) / synchronized(obj) → 鎖指定對象static synchronized void method() / synchronized(MyClass.class) → 鎖 Class 對象// 阻塞隊列版 (推薦)
BlockingQueue queue = new LinkedBlockingQueue<>(100);
// 生產者
void produce(Task t) throws InterruptedException {
queue.put(t); // 滿則阻塞
}
// 消費者
Task consume() throws InterruptedException {
return queue.take(); // 空則阻塞
}
核心優勢:無需手寫 wait/notify,內置阻塞語義,ArrayBlockingQueue (有界)、LinkedBlockingQueue (可選界)、SynchronousQueue (直接傳遞)。
ThreadLocalMap 存儲在 Thread 內,Key 為 WeakReference,Value 為任意對象try { ... } finally { threadLocal.remove(); },線程池場景必須清理new ThreadPoolExecutor(
corePoolSize, // 核心線程數
maximumPoolSize, // 最大線程數
keepAliveTime, unit, // 非核心線程存活時間
workQueue, // 任務隊列 (有界/無界)
threadFactory, // 線程工廠 (命名、優先級、守護)
handler // 拒絕策略
);
| 類型 | 核心/最大 | 隊列 | 適用場景 |
|---|---|---|---|
| FixedThreadPool | n / n | LinkedBlockingQueue (無界) | 長期固定負載,慎用 (OOM 風險) |
| CachedThreadPool | 0 / Integer.MAX | SynchronousQueue (直傳) | 短任務突發,慎用 (線程爆炸) |
| SingleThreadExecutor | 1 / 1 | LinkedBlockingQueue | 串行任務,保證順序 |
| ScheduledThreadPool | core / 無界 | DelayedWorkQueue | 定時/周期任務 |
生產建議:自定義有界隊列 + 拒絕策略,監控隊列積壓、線程數、拒絕數指標。
| 維度 | wait() | sleep() |
|---|---|---|
| 所屬類 | Object | Thread |
| 鎖狀態 | 釋放鎖 | 持有鎖 |
| 喚醒方式 | notify/notifyAll / 中斷 / 超時 | 時間到 / 中斷 |
| 調用前提 | 必須持有對象鎖 (同步塊內) | 無 |
| 語義 | 線程通信/等待條件 | 單純延時 |
| 維度 | BIO (IO) | NIO |
|---|---|---|
| 核心抽象 | Stream (流) | Channel + Buffer + Selector |
| 讀寫方式 | 阻塞 | 非阻塞/異步 |
| 線程模型 | 一連接一線程 | 一線程多連接 (Reactor) |
| 數據處理 | 順序讀寫,無緩衝區控制 | 緩衝區隨機讀寫,可前後移動 |
| 適用場景 | 連接數少、低併發 | 高併發、長連接 (Netty 基石) |
Class 對象),動態創建實例、訪問字段、調用方法Class、Constructor、Field、MethodsetAccessible(true)、緩存 Method/Field 對象、MethodHandle/VarHandle (JDK9+)、GraalVM 內聯? extends T (上界/生產者/只讀)、? super T (下界/消費者/只寫)List 不能轉為 List,但可用 List<? extends Object>| 解析器 | 模式 | 內存 | 速度 | 特點 |
|---|---|---|---|---|
| DOM | 樹模型 | 高 (全載入) | 慢 | 可修改、隨機訪問、小文件首選 |
| SAX | 事件流 | 低 (流式) | 快 | 只讀、線性、大文件、回調式 |
| StAX | 拉取流 | 低 | 快 | 可控制解析進程、雙向游標 |
| DOM4J/JDOM | 樹模型 | 中 | 中 | API 友好、XPath 支持、實際開發常用 |
javah 生成 .h → 實現 .c/.cpp → 編譯為 .so/.dll → System.loadLibrary 加載| 特性 | InnoDB | MyISAM |
|---|---|---|
| 事務 | 支持 (ACID) | 不支持 |
| 鎖粒度 | 行級鎖 | 表級鎖 |
| 外鍵 | 支持 | 不支持 |
| 全文索引 | 5.6+ 支持 | 支持 |
| count(*) | 掃表/統計估算 | 直接讀元數據 (極快) |
| 崩潰恢復 | Redo/Undo Log | 無,易損壞 |
| 適用場景 | 高併發寫、事務、可靠性要求高 | 讀多寫少、全文搜索、非關鍵數據 |
init() (一次) → service() (每請求一線程) → destroy() (一次)┌─────────────────────────────────────┐
│ 堆 │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ 新生代 │ │ 老年代 │ │
│ │ Eden + S0/S1 │ │ │ │
│ └─────────────┘ └─────────────────┘ │
├─────────────────────────────────────┤
│ 元空間 │ (類元數據、常量池、靜態變量、JIT 代碼)
├─────────────────────────────────────┤
│ 虛擬機棧 / 本地方法棧 / 程序計數器 │ (線程私有)
├─────────────────────────────────────┤
│ 直接內存 │ (NIO、Netty、DirectByteBuffer)
└─────────────────────────────────────┘
<init>| 算法 | 原理 | 優點 | 缺點 | 適用區 |
|---|---|---|---|---|
| 標記-清除 | 標記存活 → 清除死亡 | 基礎算法 | 碎片多、效率低 | 老年代 (配合整理) |
| 標記-整理 | 標記 → 移動存活對象一端 → 清理 | 無碎片 | 移動開銷大、需更新引用 | 老年代 |
| 複製 | 劃分兩塊,用一塊,存活複製到另一塊 | 無碎片、分配快 | 內存利用率 50% | 新生代 (Eden+S0/S1) |
優化思路:分代收集 (新生代複製 + 老年代標記整理/並發標記)、大對象直接進老年代、長期存活對象晋升、動態年齡判斷。
| 收集器 | 類型 | 區域 | 算法 | 特點 | 組合 |
|---|---|---|---|---|---|
| Serial | 單線程 | 新/老 | 複製/整理 | 簡單、Client 模式 | Serial Old |
| ParNew | 多線程 | 新 | 複製 | Serial 多線程版,配合 CMS | CMS |
| Parallel Scavenge | 多線程 | 新 | 複製 | 吞吐量優先、自適應調節 | Parallel Old |
| CMS | 並發 | 老 | 標記-清除 | 低停頓、CPU 敏感、浮動垃圾、碎片 | ParNew |
| G1 | 並發+並行 | 全堆 | 標記-整理+複製 | 分 Region、可預測停頓、混合收集 | 獨立 |
| ZGC/Shenandoah | 並發 | 全堆 | 著色指針/轉發指針 | 亞毫秒停頓、大堆 (TB 級) | 獨立 |
| 工具 | 功能 | 核心參數 |
|---|---|---|
| jps | 列出 Java 進程 | -l (主類), -v (JVM 參數) |
| jstat | GC/類加載/編譯統計 | -gcutil -gc -gccapacity -gcnew -gcold 間隔 次數 |
| jmap | 堆快照/直方圖 | -heap -histo:live -dump:live,format=b,file=heap.hprof |
| jstack | 線程快照 | -l (鎖信息), -m (混合模式) |
| jconsole / jvisualvm | 圖形化監控 | 遠程連接、MAT 插件分析 dump |
| Arthas | 線上診斷神器 | dashboard, trace, watch, tt, heapdump |
Class 對象<clinit> (靜態塊/靜態字段賦值),觸發條件:new/getstatic/putstatic/invokestart/reflect/主類/子類初始化/接口默認方法雙親委派:
Bootstrap (啟動) → Extension (擴展) → Application (應用) → Custom (自定義)
rt.jar lib/ext classpath 用戶定義
invokestatic/invokevirtual (參數類型)invokevirtual 查虛方法表Java 體系龐大,但核心原理貫通。掌握「為什麼這樣設計、邊界在哪、如何權衡」,面試與架構設計才能游刃有餘。祝各位 Offer 滿懷!