1. String、StringBuffer、StringBuilder區別
特性 | String | StringBuffer | StringBuilder |
---|---|---|---|
可變性 | 不可變 | 可變 | 可變 |
線程安全 | 是 | 是(synchronized) | 否 |
性能 | 低(頻繁操作時) | 中等 | 高 |
場景 | 字符串常量 | 多線程字符串操作 | 單線程字符串操作 |
2. 接口和抽象類的區別
特性 | 接口(Interface) | 抽象類(Abstract Class) |
---|---|---|
實現/繼承 | 多實現 | 單繼承 |
方法實現 | Java 8前無實現 | 可有實現 |
變量 | 只能是常量 | 普通變量 |
構造方法 | 無 | 有 |
設計目的 | 定義行為規范 | 代碼復用 |
3. Thread和Runnable區別
Thread:繼承方式,單繼承限制
Runnable:接口實現,更靈活,資源共享方便
推薦:優先使用Runnable,符合面向接口編程
4. 接口支持靜態方法嗎?
支持(Java 8+):
interface MyInterface {static void staticMethod() {System.out.println("靜態方法");} }
5. TLS通信機制
握手階段:協商加密算法、交換密鑰
證書驗證:驗證服務器身份
對稱加密:使用會話密鑰加密通信
關鍵點:前向安全、混合加密
6. CA發的是私鑰還是公鑰?
CA頒發的是包含公鑰的數字證書,私鑰由申請者自己保管。
7. List、Set、Map的區別
集合類型 | 順序 | 重復 | 空值 | 實現類 |
---|---|---|---|---|
List | 有序 | 允許 | 允許多個 | ArrayList, LinkedList |
Set | 無序 | 不允許 | 最多一個 | HashSet, TreeSet |
Map | 無序 | key唯一 | HashMap允許一個null key | HashMap, TreeMap |
8. List的訪問方式
索引訪問:
list.get(index)
迭代器:
Iterator
/ListIterator
for-each循環
Java 8+ Stream API
9. ArrayList和LinkedList區別
特性 | ArrayList | LinkedList |
---|---|---|
底層 | 動態數組 | 雙向鏈表 |
訪問 | O(1)隨機訪問 | O(n)順序訪問 |
增刪 | O(n) | O(1)首尾操作 |
內存 | 連續空間 | 節點+指針 |
10. HashMap加載因子
默認0.75是空間與時間的平衡點:
過高:哈希沖突增加
過低:內存浪費
擴容觸發:元素數 > 容量×加載因子
11. 線程和進程區別
維度 | 進程 | 線程 |
---|---|---|
資源 | 獨立內存空間 | 共享進程資源 |
切換開銷 | 大 | 小 |
通信 | IPC(管道等) | 共享內存(需同步) |
健壯性 | 一個崩潰不影響其他 | 線程崩潰影響整個進程 |
12. View和ViewGroup點擊事件傳遞機制
事件傳遞流程(以ACTION_DOWN為例):
分發階段(自上而下):
Activity.dispatchTouchEvent() → Window → DecorView
每個ViewGroup的dispatchTouchEvent()調用onInterceptTouchEvent()
如果未被攔截,繼續向子View傳遞
處理階段(自下而上):
最底層View的onTouchEvent()首先獲得處理機會
若未處理,事件回傳給父ViewGroup
最終可由Activity.onTouchEvent()處理
關鍵方法:
public boolean dispatchTouchEvent(MotionEvent ev) {// 1. 判斷是否攔截if (onInterceptTouchEvent(ev)) {return super.dispatchTouchEvent(ev);}// 2. 遍歷子View處理for (View child : children) {if (child.dispatchTouchEvent(ev)) {return true;}}// 3. 自身處理return onTouchEvent(ev); }
事件沖突解決方案:
外部攔截法:重寫父容器的onInterceptTouchEvent()
內部攔截法:子View調用requestDisallowInterceptTouchEvent()
典型場景:ScrollView內嵌ListView
13. B樹與B+樹深度對比
B樹結構特性:
所有節點存儲數據
關鍵字分布在整個樹中
非葉子節點也包含數據指針
B+樹結構特性:
數據僅存于葉子節點
葉子節點通過指針鏈接
非葉子節點只作索引
性能對比表:
特性 | B樹 | B+樹 |
---|---|---|
查詢時間復雜度 | O(log?n)不穩定 | O(log?n)穩定 |
范圍查詢效率 | 需要中序遍歷 | 鏈表順序訪問O(1) |
磁盤IO次數 | 隨機訪問可能更多 | 更穩定更少 |
內存利用率 | 非葉節點存數據 | 非葉節點純索引 |
14. 數據庫索引選擇B+樹的原因
工程化優勢:
IO優化:
節點大小設計為磁盤頁大小(通常4KB)
單次IO能加載更多鍵值
查詢穩定性:
所有查詢都要走到葉子節點
避免B樹中非葉節點命中導致的查詢時間波動
范圍查詢優化:
-- B+樹能高效處理 SELECT * FROM table WHERE id BETWEEN 100 AND 200;
葉子節點鏈表實現O(1)復雜度范圍遍歷
全盤掃描優勢:
遍歷葉子節點鏈表即可獲得有序數據
避免B樹的樹形遍歷
15. 平衡樹類型辨析
平衡二叉樹對比多路平衡樹:
關鍵區別:
節點容量:
二叉樹:每個節點最多2個子節點
B/B+樹:每個節點通常有幾百子節點(取決于磁盤頁大小)
平衡方式:
AVL樹:嚴格平衡(高度差≤1)
紅黑樹:近似平衡(最長路徑≤2倍最短)
B/B+樹:通過分裂/合并保持平衡
適用場景:
內存查找:紅黑樹
磁盤索引:B+樹
16. 排序算法復雜度
時間復雜度:平均O(nlogn),最差O(n2)(已排序數組)
空間復雜度:O(logn)遞歸棧
歸并排序實現:
時間復雜度:穩定O(nlogn)
空間復雜度:O(n)臨時數組
17. Java繪制過程詳解
View繪制三階段:
Measure階段:
protected void onMeasure(int widthSpec, int heightSpec) {// 根據父容器的MeasureSpec和自身LayoutParams計算int width = calculateWidth(widthSpec);int height = calculateHeight(heightSpec);setMeasuredDimension(width, height); // 必須調用 }
MeasureSpec包含模式和大小(EXACTLY/AT_MOST/UNSPECIFIED)
Layout階段:
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {// ViewGroup需遍歷布局所有子Viewfor (View child : children) {child.layout(childLeft, childTop, childRight, childBottom);} }
Draw階段:
protected void onDraw(Canvas canvas) {// 示例:繪制圓角矩形Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setColor(Color.BLUE);RectF rect = new RectF(0, 0, getWidth(), getHeight());canvas.drawRoundRect(rect, 20, 20, paint); }
繪制順序:背景→主體→子View→裝飾
性能優化點:
減少View層級
使用ViewStub延遲加載
避免在onDraw中創建對象
18. OSI七層模型數據處理
HTTP請求在各層的封裝:
應用層:HTTP頭 + 數據(GET /index.html HTTP/1.1) 表示層:數據加密/壓縮(HTTPS增加TLS加密) 會話層:建立/維護會話(Cookie/Session管理) 傳輸層:TCP頭 + 端口號(源端口54321 → 目標端口80) 網絡層:IP頭 + IP地址(192.168.1.2 → 216.58.200.46) 數據鏈路層:MAC頭 + CRC(源MAC → 網關MAC) 物理層:比特流(電信號/光信號傳輸)
19. TCP工作原理深度解析
三次握手建立連接:
客戶端 → SYN=1, seq=x → 服務端 客戶端 ← SYN=1, ACK=1, seq=y, ack=x+1 ← 服務端 客戶端 → ACK=1, seq=x+1, ack=y+1 → 服務端
可靠傳輸機制:
序號確認:
每個字節都有唯一序號
接收方發送ACK確認收到的連續數據
滑動窗口:
// 典型窗口結構 struct {uint32_t left; // 窗口左邊界uint32_t right; // 窗口右邊界uint32_t size; // 窗口大小(根據擁塞控制調整) } sliding_window;
實現流量控制和擁塞避免
超時重傳:
RTO(Retransmission Timeout)動態計算:
RTO = SRTT + max(G, K×RTTVAR)
其中SRTT是平滑RTT,RTTVAR是方差
四次揮手釋放連接:
客戶端 → FIN=1, seq=u → 服務端 客戶端 ← ACK=1, ack=u+1 ← 服務端 ...(服務端數據發送完畢)... 客戶端 ← FIN=1, seq=v, ack=u+1 ← 服務端 客戶端 → ACK=1, seq=u+1, ack=v+1 → 服務端
20. 死鎖及避免方法
死鎖定義:多個線程互相持有對方需要的資源,導致所有線程無限期阻塞的狀態。
四個必要條件:
互斥條件(資源獨占)
占有且等待(持有資源并請求新資源)
不可搶占(資源不能被強制釋放)
循環等待(存在等待環路)
避免方案:
方案1:破壞循環等待(固定鎖獲取順序) 方案2:使用tryLock(破壞不可搶占)
21. 虛擬內存與內存管理
虛擬內存核心功能:
地址空間隔離(每個進程有獨立4GB空間)
按需分頁(Page Fault機制)
頁面置換(LRU算法)
分頁 vs 分段:
特性 | 分頁 | 分段 |
---|---|---|
劃分單位 | 固定大小(4KB) | 邏輯單元(代碼/數據段) |
碎片問題 | 內部碎片 | 外部碎片 |
管理方式 | 頁表(多級/TLB加速) | 段表 |
優勢場景 | 通用內存管理 | 模塊化程序 |
現代實現:段頁式結合(Linux使用扁平化段模式+分頁)
22.排序算法的時間復雜度、空間復雜度及穩定性對比
排序算法 | 平均時間復雜度 | 最好情況 | 最壞情況 | 空間復雜度 | 穩定性 | 關鍵特性 |
---|---|---|---|---|---|---|
冒泡排序 | O(n2) | O(n)(已優化) | O(n2) | O(1) | 穩定 | 相鄰元素比較交換,適合小規模數據 |
選擇排序 | O(n2) | O(n2) | O(n2) | O(1) | 不穩定 | 每次選最小元素交換,交換次數最少(O(n)次) |
插入排序 | O(n2) | O(n)(已排序) | O(n2) | O(1) | 穩定 | 類似撲克牌排序,對基本有序數據效率高 |
希爾排序 | O(n^1.3) | O(n log n) | O(n2) | O(1) | 不穩定 | 插入排序改進版,通過分組增量提高效率 |
歸并排序 | O(n log n) | O(n log n) | O(n log n) | O(n) | 穩定 | 分治法典范,需額外空間,適合外部排序 |
快速排序 | O(n log n) | O(n log n) | O(n2)(極端) | O(log n) | 不穩定 | 實際最快的內排序,遞歸棧空間消耗,需合理選擇pivot |
堆排序 | O(n log n) | O(n log n) | O(n log n) | O(1) | 不穩定 | 利用堆結構,適合大數據TopK問題 |
計數排序 | O(n + k) | O(n + k) | O(n + k) | O(k) | 穩定 | 非比較排序,k為數據范圍,適合密集整數數據 |
桶排序 | O(n + k) | O(n) | O(n2)(極端) | O(n + k) | 穩定 | 數據均勻分布時高效,依賴桶劃分策略 |
基數排序 | O(n × k) | O(n × k) | O(n × k) | O(n + k) | 穩定 | 按位排序(LSD/MSD),k為最大位數 |
23. 代碼維護工具集
高效開發工具鏈:
關鍵工具使用場景:
Git:
git bisect
快速定位問題提交ADB:
adb shell dumpsys
獲取系統狀態MAT:分析內存泄漏
LeakCanary:自動化內存檢測
24. Android異步加載方案
現代異步編程演進:
基礎方案:
// HandlerThread示例 val handlerThread = HandlerThread("Worker").apply { start() } val handler = Handler(handlerThread.looper) handler.post { /* 后臺任務 */ }
協程方案(推薦):
viewModelScope.launch {val data = withContext(Dispatchers.IO) { repository.fetchData() }updateUI(data) // 自動切回主線程 }
性能對比:
方案 | 線程開銷 | 代碼可讀性 | 生命周期管理 |
AsyncTask | 中 | 較好 | 差 |
RxJava | 低 | 較差 | 中 |
協程 | 極低 | 優秀 | 優秀 |
25. equals()與hashCode()
維度 | equals() | hashCode() |
---|---|---|
用途 | 比較兩個對象的內容是否邏輯相等 | 生成對象的哈希碼值 |
重寫要求 | 必須與hashCode() 保持一致 | 必須與equals() 保持一致 |
性能 | 可能較慢(深比較) | 必須高效(O(1)復雜度) |
默認實現 | Object 類中比較內存地址(== ) | Object 類中返回對象內存地址的哈希值 |
26. MVC架構解析
Android中的MVC實現:
典型問題:
Activity同時承擔Controller和View職責
業務邏輯與UI耦合
改進方案:引入MVP/MVVM
27. Java多線程核心參數
線程池參數詳解:
ThreadPoolExecutor(int corePoolSize, // 常駐線程數(不會回收)int maximumPoolSize, // 最大線程數(臨時線程)long keepAliveTime, // 臨時線程存活時間TimeUnit unit, // 時間單位BlockingQueue<Runnable> workQueue, // 任務隊列RejectedExecutionHandler handler // 拒絕策略 )
四種拒絕策略:
AbortPolicy(默認):拋出RejectedExecutionException
CallerRunsPolicy:用調用者線程執行
DiscardPolicy:靜默丟棄
DiscardOldestPolicy:丟棄隊列最老任務
28. SharedPreferences實踐
安全寫入方式:
// 最佳實踐:apply()異步寫入(無返回值) val prefs = getSharedPreferences("user", MODE_PRIVATE) prefs.edit().putString("name", "Alice").putInt("age", 25).apply()// 需要結果時使用commit() val success = prefs.edit().clear().commit()
數據存儲格式:
基本類型:直接存儲(int, float, boolean等)
復雜對象:
// 序列化為JSON存儲 val gson = Gson() val userJson = gson.toJson(userObj) prefs.edit().putString("user", userJson).apply()// 讀取時反序列化 val restored = gson.fromJson(prefs.getString("user", ""), User::class.java)
29. 自定義View開發要點
實現步驟:
繼承View或其子類
處理自定義屬性:
<!-- res/values/attrs.xml --> <declare-styleable name="MyView"><attr name="customColor" format="color" /> </declare-styleable>
重寫關鍵方法:
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {// 計算視圖大小setMeasuredDimension(calculatedWidth, calculatedHeight) }override fun onDraw(canvas: Canvas) {// 使用Paint進行繪制canvas.drawCircle(centerX, centerY, radius, paint) }
性能優化:
避免在onDraw中分配對象
使用canvas.clipRect()限制繪制區域
考慮硬件加速特性
30. OnClick事件本質
底層實現原理:
// 實際是View.OnClickListener接口 public interface OnClickListener {void onClick(View v); }// 設置監聽后的調用鏈 View.performClick() → ListenerInfo.mOnClickListener.onClick() → 用戶代碼
與onTouchEvent關系:
31. SpringCloud Alibaba核心部件
Nacos:服務注冊與發現、配置中心
Sentinel:流量控制、熔斷降級
Seata:分布式事務解決方案
RocketMQ:消息隊列(可選組件)
Dubbo RPC:遠程服務調用(可選)
32. 服務注冊與發現過程
服務注冊:
服務發現:
健康檢查:Nacos通過心跳檢測(15秒間隔)判斷服務存活
33. 微服務負載均衡機制
客戶端負載均衡(SpringCloud默認):
通過
Ribbon
或LoadBalancer
實現服務消費者本地維護服務列表并選擇實例
服務端負載均衡:
如Nginx、API網關等代理流量
34. 負載均衡策略
策略 | 描述 | 適用場景 |
---|---|---|
輪詢(RoundRobin) | 依次分配請求 | 默認場景 |
隨機(Random) | 隨機選擇實例 | 測試環境 |
加權響應時間(Weighted) | 根據響應時間動態調整權重 | 性能差異大的集群 |
最小并發(LeastActive) | 選擇當前并發請求最少的實例 | 長任務處理 |
服務宕機處理流程:
Nacos心跳檢測失敗(15秒×3次)
標記實例為不健康
30秒后從注冊列表刪除
通知訂閱該服務的消費者更新列表
35. 微服務高可用保障
多實例部署:單服務至少2個實例
集群化注冊中心:Nacos集群(3節點以上)
熔斷降級:Sentinel自動隔離故障服務
限流保護:防止突發流量打垮系統
異地多活:跨機房部署(如阿里云多可用區)
36. 服務雪崩與解決方案
雪崩效應:A服務故障→B服務重試→B資源耗盡→C服務受影響→連鎖故障
解決方案:
熔斷(Sentinel):
// 當失敗率>50%時熔斷10秒 @SentinelResource(fallback = "fallbackMethod")
降級:返回緩存數據或默認值
限流:控制QPS閾值
37. 熔斷與限流過程
熔斷流程:
統計時間窗口內(如1分鐘)的失敗率
達到閾值(如50%)觸發熔斷
所有請求直接走fallback邏輯
經過冷卻期后嘗試恢復
限流流程:
計數器統計當前QPS
超過閾值時拒絕請求(直接拒絕/排隊等待)
支持集群限流(通過Redis實現)
38. 常見限流算法
算法 | 原理 | 特點 |
---|---|---|
計數器 | 固定時間窗口計數 | 實現簡單,有臨界問題 |
滑動窗口 | 細分時間塊統計 | 緩解臨界問題 |
漏桶 | 恒定速率處理請求 | 平滑流量,無法應對突發 |
令牌桶 | 定期放入令牌,請求消耗令牌 | 允許突發流量(最常用) |
39. 令牌桶實現(Guava RateLimiter)
// 創建每秒2個令牌的桶 RateLimiter limiter = RateLimiter.create(2.0); void handleRequest() {if (limiter.tryAcquire()) { // 獲取令牌processRequest();} else {throw new RateLimitException();} }
底層數據結構:基于SmoothBursty
算法實現
40. 秒殺系統挑戰
瞬時高并發:QPS可能達10萬+
超賣問題:庫存扣減的原子性
惡意請求:機器人刷單
系統瓶頸:數據庫扛不住
解決方案:
分層過濾(限流→緩存→異步扣庫存)
Redis原子操作(DECR+Lua腳本)
消息隊列削峰填谷
41. 分布式事務實現
典型方案:
Seata AT模式(默認):
一階段:提交本地事務
二階段:異步提交/回滾
TCC模式(Try-Confirm-Cancel):
Saga模式:長事務補償機制
42. 三階段提交(3PC)詳解
設計目標:解決2PC的阻塞問題,提高分布式事務的可用性
三個階段:
CanCommit階段(協調者→參與者)
協調者發送
CanCommit?
請求,詢問參與者是否具備提交條件參與者檢查資源鎖定、日志空間等,回復
Yes/No
PreCommit階段(協調者決策)
全部Yes:協調者發送
PreCommit
命令,參與者執行事務操作(寫redo log)但不提交有No響應:協調者發送
Abort
命令終止事務
DoCommit階段(最終提交)
協調者發送
DoCommit
,參與者完成提交若協調者未收到響應,超時后自動提交(相比2PC減少阻塞)
關鍵改進:
引入超時機制:參與者長時間未收到指令可自動提交(避免無限阻塞)
增加預提交階段:降低資源鎖定時間
43. 三階段提交的缺點
性能問題:
比2PC多一輪網絡通信(3次交互 vs 2次)
吞吐量下降約30%
腦裂風險:
網絡分區時可能出現部分提交、部分回滾的不一致狀態
示例:協調者與部分參與者失聯,未收到
DoCommit
的節點超時提交,其他節點回滾
實現復雜度高:
需處理超時、狀態恢復等邊界條件
對開發者不透明(Seata等框架已封裝)
適用場景:
對可用性要求高于一致性的系統
跨多數據中心的分布式事務
44. 分布式事務開源框架
框架 | 模式 | 特點 | 適用場景 |
---|---|---|---|
Seata | AT/TCC/Saga | 阿里開源,社區活躍,支持多模式 | 通用微服務 |
RocketMQ事務消息 | 最終一致性 | 基于消息隊列,異步解耦 | 訂單支付等異步流程 |
Hmily | TCC | 金融級設計,強一致性 | 資金交易等高要求場景 |
LCN | 代理模式 | 通過代理連接池管理事務 | 傳統系統改造 |
選型建議:
快速接入:Seata AT模式(零代碼侵入)
高性能:RocketMQ事務消息
強一致:TCC模式(需業務實現Try/Confirm/Cancel)
45. Kafka核心用途
實時數據管道:
日志收集(ELK架構)
指標監控(Prometheus + Kafka)
事件驅動架構:
流處理基礎:
與Flink/Spark Streaming集成
實現實時數據分析(如用戶點擊流)
典型場景:
電商訂單狀態變更廣播
IoT設備數據匯聚
46. 傳統消息隊列對比
消息隊列 | 協議 | 設計目標 |
---|---|---|
RabbitMQ | AMQP | 企業級消息路由 |
ActiveMQ | JMS | 老牌Java生態支持 |
RocketMQ | 自定義協議 | 金融級高可靠 |
共同特點:
支持隊列/主題模式
提供ACK機制
需額外組件實現高吞吐(如RabbitMQ集群)
47. Kafka的優勢
核心優勢點:
吞吐量:單集群百萬級QPS(通過分區橫向擴展)
持久化:消息默認保存7天(可配置為永久)
消費者組:支持多組獨立消費同一Topic
順序性:同一分區內消息嚴格有序
技術實現:
零拷貝:減少內核態到用戶態的數據復制
頁緩存:直接讀寫OS緩存提升IO效率
批量發送:減少網絡IO次數
48. Kafka事務支持
實現原理:
生產者事務:
// 啟用事務 props.put("enable.idempotence", "true"); props.put("transactional.id", "tx-1"); producer.initTransactions(); // 事務操作 producer.beginTransaction(); producer.send(record1); producer.send(record2); producer.commitTransaction();
消費-生產模式:
確保消費后處理的原子性
通過
isolation.level=read_committed
避免臟讀
限制:
事務主要針對生產者
消費端仍需處理冪等(如業務去重表)
49. RabbitMQ事務
基本用法:
channel.txSelect(); // 開啟事務 try { channel.basicPublish(...); channel.txCommit(); } catch (Exception e) { channel.txRollback(); }
性能影響:
事務模式吞吐量下降約200倍
替代方案:
Confirm模式:異步確認消息落地
持久化+ACK:保障消息不丟失
50. RabbitMQ適用場景
復雜路由邏輯:
python
# 根據消息頭路由到不同隊列 channel.exchange_declare(exchange='logs', type='headers')
延遲隊列:
通過
x-dead-letter-exchange
?+ TTL實現
優先級隊列:
典型用例:
電商訂單超時取消
客服系統消息優先級處理
51. 引入中間件的問題
常見挑戰:
消息丟失:
Kafka:需配置
acks=all
?+ 副本同步RabbitMQ:開啟持久化 + Confirm機制
重復消費:
解決方案:業務冪等設計(如唯一鍵約束)
運維復雜度:
監控指標:堆積數、消費延遲、錯誤率
工具:Kafka Eagle/RabbitMQ Management Plugin
架構建議:
消息中間件與業務解耦
建立消息治理規范(如命名規則、TTL設置)
52. 消息積壓處理方案
應急步驟:
擴容消費者:
降級處理:
跳過非核心消息(如日志類數據)
批量消費提升效率
根本解決:
優化消費邏輯:
避免同步IO(如DB查詢改為批量)
使用本地緩存
限流保護:
53. 死信隊列(DLQ)機制
觸發條件:
消息被拒絕(
basic.reject
或basic.nack
)且requeue=false
消息TTL過期
隊列達到最大長度
應用場景:
異常處理:人工檢查失敗消息
延遲隊列:通過TTL+DLQ實現定時任務
審計跟蹤:記錄所有失敗消息