一、Java 基礎
1. JVM 相關
-
Q:什么情況下會發生棧內存溢出? A:就像食堂打飯窗口前排隊,隊伍太長(方法調用層級太深),或者每個人占的位置太大(局部變量太多),隊伍擠不下就會 “溢出”。具體來說,遞歸調用沒終止條件,或者方法里定義超大數組,都會導致棧內存不夠用。
-
Q:JVM 的主要組成部分及其作用? A:JVM 像一個工廠,主要部門包括:
- 類加載器:負責把 Java 代碼(.class 文件)翻譯成工廠能看懂的 “說明書”;
- 內存區域:分配空間放數據(比如堆存對象,棧存方法調用);
- 執行引擎:按說明書干活,執行字節碼指令;
- 垃圾回收器:清理工廠里的廢品(不再用的對象)。
-
Q:垃圾回收機制和常見收集器? A:GC 就像掃地阿姨,定期清理 “垃圾對象”(沒人引用的對象)。常見掃地阿姨有:
- Serial 收集器:單線程打掃,簡單粗暴,適合小房間(單 CPU 場景);
- Parallel 收集器:多線程一起掃,效率高,適合大工廠(多核服務器);
- CMS/G1 收集器:更聰明的阿姨,邊干活邊掃,減少工廠停工時間(低停頓場景)。
2. 多線程相關
-
Q:線程和進程的區別? A:進程像一個獨立的車間(比如微信程序),線程是車間里的工人。一個車間可以有多個工人(多線程),共享車間資源(內存、文件),工人干活更輕量(創建銷毀更快)。
-
Q:如何實現線程同步? A:比如多個工人同時用一臺機器,需要 “排隊”:
- synchronized:給機器加鎖,誰拿到鎖誰用(如
?synchronized(this){...}
); - Lock 接口:更靈活的鎖,能中途放棄排隊(如
ReentrantLock
); - 原子類:比如
AtomicInteger
,保證數字操作不會被打斷(類似自動售貨機計數)。
- synchronized:給機器加鎖,誰拿到鎖誰用(如
-
Q:線程池的原理和常用類? A:線程池像一個工人儲備庫,提前招好工人(創建線程),有任務就派工人干,干完不辭退,下次接著用。常用類:
ThreadPoolExecutor
:最基礎的線程池,可自定義參數;Executors工具類
:快速創建常見線程池(如newFixedThreadPool
固定線程數)。
二、數據庫
1. MySQL 基礎
-
Q:事務的四大特性?隔離級別和默認級別? A:事務像轉賬操作,必須滿足:
- ACID:
- 原子性(要么全成功,要么全失敗,比如轉賬不能只扣錢不進賬);
- 一致性(轉賬前后總金額不變);
- 隔離性(多個轉賬互不干擾);
- 持久性(成功后永久保存)。 隔離級別(從低到高):讀未提交(可能讀到臟數據)、讀已提交(MySQL 默認)、可重復讀、串行化(性能最差但最安全)。
- ACID:
-
Q:樂觀鎖和悲觀鎖的區別? A:悲觀鎖像搶車位,提前占住(加鎖),別人不能用;樂觀鎖像先停車,走的時候檢查有沒有人動過(版本號對比),適合沖突少的場景(如商品庫存更新)。
-
Q:CHAR 和 VARCHAR 的區別? A:CHAR 是固定長度的盒子(如 CHAR (10) 永遠占 10 個位置),適合短且固定的數據(如性別);VARCHAR 是可變長度的盒子,數據多長就占多大空間,適合內容不確定的字段(如文章摘要)。
2. 索引相關
-
Q:索引為什么快?底層數據結構? A:索引像字典的目錄,比如查 “Java”,直接翻到 J 開頭的頁,不用逐頁找。MySQL 索引底層是 B + 樹,數據按順序排列,查詢時像爬樹,快速定位。
-
Q:索引失效的原因? A:比如目錄被破壞:
- 字段用函數(如
SELECT * FROM user WHERE YEAR(create_time)=2025
); - 模糊查詢以通配符開頭(如
LIKE '%java'
); - 類型不匹配(如字段是數字,查詢時傳字符串
'123'
)。
- 字段用函數(如
-
Q:最左前綴匹配原則? A:復合索引(如
idx_name_age
)像按 “姓名 + 年齡” 排序的名單,查詢時必須先按姓名查,再按年齡查。如果只查年齡,索引就用不上(除非姓名也在條件里)。
3. Redis 相關
-
Q:Redis 常見數據類型? A:比 MySQL 更靈活的 “抽屜”:
String
:存單個值(如key:value
);List
:存隊列(如聊天記錄,按順序存);Hash
:存對象(如用戶信息,user:1
包含name
、age
字段);Set
:存不重復的集合(如點贊用戶);ZSet
:帶分數的集合(如排行榜,按分數排序)。
-
Q:緩存雪崩和穿透怎么解決? A:
- 雪崩:大量緩存同時過期,像超市開門瞬間擠爆。解決:給緩存過期時間加隨機值,避免同時失效;
- 穿透:黑客查不存在的數據,像一直敲空門。解決:用布隆過濾器先過濾不存在的 key,或者緩存空結果(短時間)。
-
Q:Redis 內存滿了怎么辦? A:按規則扔東西,常見策略:
LRU
:扔最久沒用的;LFU
:扔用得最少的;Random
:隨機扔(不推薦)。
三、框架相關
1. Spring 框架
-
Q:Spring 框架和核心模塊? A:Spring 像一個 “萬能工具包”,幫你組裝程序:
- IoC 容器:自動管理對象創建和依賴(比如你要泡茶,IoC 會自動給你杯子、茶葉);
- AOP:給程序加 “插件”(如日志、事務),不修改原代碼;
- 其他模塊:Spring MVC(處理 Web 請求)、Spring Data(操作數據庫)等。
-
Q:IoC 和 AOP 的理解? A:
- IoC(控制反轉):以前你自己找對象(new),現在對象由 Spring 管理,你直接用(像外賣送到家);
- AOP(面向切面編程):比如給所有方法加日志,不用每個方法里寫
System.out
,而是像 “切蛋糕” 一樣,在方法執行前后統一處理。
-
Q:Spring Bean 的生命周期? A:Bean(對象)的一生:
- 被 Spring 創建;
- 初始化前(調用
@PostConstruct
注解方法); - 初始化(如設置屬性、調用
init-method
); - 被使用;
- 銷毀前(調用
@PreDestroy
); - 銷毀(如容器關閉)。
2. Spring Boot
-
Q:Spring Boot 和 Spring 的區別? A:Spring 像自己組裝電腦(需要配置很多東西),Spring Boot 像品牌機,默認配置好常用功能(如自動配置 Tomcat、數據庫連接),開箱即用,減少代碼量。
-
Q:Spring Boot 自動配置原理? A:啟動時,Spring Boot 會掃描 “啟動器”(如
spring-boot-starter-web
),根據依賴自動加載對應的配置類(如 Tomcat 配置、MVC 配置),就像你買了 “Web 啟動器”,電腦自動裝好瀏覽器、網絡驅動。
3. MyBatis
-
**Q:#{} 和 ${} 的區別?** A:`\#{}`是預編譯占位符(像`?`),防SQL注入(如`SELECT * FROM user WHERE id=\#{id}`);${}
是直接拼接字符串(如
ORDER BY ${field}`),使用時要小心注入風險(必須確保參數安全)。 -
Q:MyBatis 緩存機制? A:一級緩存(默認開啟):像瀏覽器緩存,同一方法內查相同數據直接取緩存;二級緩存:像全局緩存,不同方法、甚至不同 Mapper 都能共享(需要手動配置
cache
標簽)。
四、分布式與微服務
1. RPC 相關
-
Q:RPC 和常見框架? A:RPC 像打電話,讓不同電腦上的程序互相調用(比如 A 服務器調 B 服務器的方法)。常見框架:Dubbo、gRPC、Spring Cloud Feign。
-
Q:為什么用 RPC 而不是 HTTP? A:HTTP 像寄信,內容多(JSON/XML)、速度慢;RPC 像打電話,內容更精簡(二進制數據)、效率更高,適合內部服務快速調用。
2. Dubbo
-
Q:Dubbo 工作原理和注冊中心? A:Dubbo 像中介平臺:
- 服務提供者(商家)把服務注冊到注冊中心(中介);
- 服務消費者(用戶)從注冊中心查商家地址,直接調用服務;
- 注冊中心(如 ZooKeeper)負責記錄商家在線狀態,相當于 “電話簿”。
-
Q:Dubbo 負載均衡策略? A:多個商家時,決定調用哪個:
- 隨機(像抽簽);
- 輪詢(按順序輪流);
- 權重(根據商家 “能力” 分配,如配置
weight=100
)。
3. 消息隊列
-
Q:為什么用消息隊列? A:像快遞中轉站,解決高峰期擁堵:
- 削峰:訂單高峰期,先把請求存隊列,慢慢處理;
- 解耦:訂單系統和物流系統不直接連,通過隊列傳遞消息,一方掛了不影響另一方。
-
Q:如何保證消息不重復消費? A:給每個消息貼唯一標簽(如 UUID),消費時記錄已處理的標簽,重復消息來了直接忽略(類似快遞單號,簽收一次后不再處理)。
五、其他高頻問題
1. 設計模式
-
Q:項目中用過哪些設計模式? A:比如:
- 單例模式(如全局唯一的配置類,
private static
實例); - 工廠模式(根據參數創建不同的服務類,如
UserServiceFactory.create("admin")
); - 觀察者模式(訂單狀態變化時,自動通知物流系統,類似微信消息推送)。
- 單例模式(如全局唯一的配置類,
-
Q:單一職責和開閉原則? A:
- 單一職責:一個類只干一件事(如
UserService
只處理用戶邏輯,不負責日志); - 開閉原則:對擴展開放,對修改關閉(加新功能時不修改原代碼,而是新增類,如新增支付方式時,繼承
Payment
接口)。
- 單一職責:一個類只干一件事(如
2. 網絡編程
-
Q:BIO、NIO、AIO 的區別? A:
- BIO:像排隊買票,必須等前面的人買完才輪到你(同步阻塞);
- NIO:像超市收銀,你先取號,逛一圈再回來問有沒有輪到(同步非阻塞);
- AIO:像外賣,下單后不用管,做好了直接送上門(異步非阻塞)。
-
Q:Netty 為什么比 NIO 好用? A:NIO 是毛坯房,需要自己組裝(Selector、Channel 等);Netty 是精裝房,封裝了底層細節,提供更易用的 API,還解決了 NIO 的 bug(如 epoll 空輪詢),適合高并發場景(如聊天服務器)。
3. 權限認證
-
Q:認證和授權的區別? A:認證是 “你是誰”(如賬號密碼登錄),授權是 “你能做什么”(如管理員能刪數據,普通用戶不能)。
-
Q:JWT 如何實現身份驗證? A:JWT 像電子身份證:
- 登錄成功后,服務器生成包含用戶信息的 JWT 字符串;
- 客戶端每次請求帶 JWT(如放在 Header);
- 服務器解析 JWT,驗證簽名是否有效,確認用戶身份。
記憶技巧
- 類比生活場景:把技術概念比作 “食堂排隊”“快遞中轉站” 等,更容易聯想;
- 抓核心關鍵詞:如事務 ACID、索引 B + 樹、JWT “電子身份證”;
- 結合項目經驗:回答時穿插實際場景(如 “我們項目用 Redis 緩存商品列表,解決了高峰期查詢慢的問題”)。