1、對線程安全的理解
線程安全是指在多線程環境下,某個函數、類或數據結構能夠正確地處理多個線程的并發訪問,而不會出現數據競爭、不一致或其他不可預期的行為。線程安全的實現通常需要考慮以下幾點:
原子性:操作是不可分割的,要么全部執行,要么全部不執行。
可見性:一個線程對共享數據的修改能夠及時被其他線程看到。
有序性:程序的執行順序符合預期,避免指令重排導致的問題。
實現線程安全的方法包括:
使用同步機制(如鎖、信號量)。
使用線程安全的數據結構(如?
ConcurrentHashMap
)。避免共享狀態(如使用局部變量或線程本地存儲)。
2、對鏈表的使用和理解,鏈表有哪幾種并舉例應用場景
鏈表是一種線性數據結構,由節點組成,每個節點包含數據和指向下一個節點的指針。鏈表的類型包括:
單向鏈表:每個節點只有一個指針指向下一個節點。
應用場景:實現棧、隊列、簡單的動態集合。
雙向鏈表:每個節點有兩個指針,分別指向前一個和后一個節點。
應用場景:需要雙向遍歷的場景(如瀏覽器的前進后退、LRU緩存)。
循環鏈表:尾節點指向頭節點,形成環。
應用場景:輪詢調度、環形緩沖區。
鏈表的優點是插入和刪除高效(O(1)),缺點是隨機訪問慢(O(n))。
3、TCP 相對于 UDP 有哪些優點,兩者的不同點
TCP的優點:
可靠傳輸:通過確認、重傳、流量控制和擁塞控制確保數據不丟失、不重復、按序到達。
面向連接:通信前需要建立連接(三次握手),通信后釋放連接(四次揮手)。
適合對可靠性要求高的場景(如文件傳輸、網頁瀏覽)。
TCP vs UDP:
特性 | TCP | UDP |
---|---|---|
可靠性 | 可靠 | 不可靠 |
連接 | 面向連接 | 無連接 |
傳輸效率 | 較低(開銷大) | 較高(開銷小) |
數據順序 | 保證順序 | 不保證順序 |
應用場景 | HTTP、FTP、SSH | 視頻流、DNS、游戲 |
4、講述一下TCP 的傳送數據的過程
建立連接(三次握手):
客戶端發送?
SYN=1, seq=x
。服務端回復?
SYN=1, ACK=1, seq=y, ack=x+1
。客戶端發送?
ACK=1, seq=x+1, ack=y+1
。
數據傳輸:
發送方將數據分割為報文段,按序發送。
接收方確認收到數據(ACK)。
發送方未收到ACK時會重傳。
釋放連接(四次揮手):
客戶端發送?
FIN=1, seq=u
。服務端回復?
ACK=1, ack=u+1
。服務端發送?
FIN=1, seq=v
。客戶端回復?
ACK=1, ack=v+1
。
5、原子性和一致性
原子性(Atomicity):事務中的操作要么全部成功,要么全部失敗(如轉賬:A減錢和B加錢必須同時完成)。
一致性(Consistency):事務執行前后,數據庫從一個一致狀態變到另一個一致狀態(如滿足約束條件)。
6、數據庫的索引和事務是什么
索引:加速查詢的數據結構(如B+樹索引)。優點:提高查詢速度;缺點:占用空間,降低插入/更新速度。
事務:一組操作的邏輯單元,滿足ACID特性(原子性、一致性、隔離性、持久性)。
7、數據庫查詢操作有哪些可以提高查詢效率的優化
使用索引。
避免?
SELECT *
,只查詢需要的列。優化JOIN操作(小表驅動大表)。
避免全表掃描(如避免對索引列使用函數)。
分庫分表(大數據量時)。
使用緩存(如Redis)。
8、手寫快排的代碼
public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (low < high) {int pivotIndex = partition(arr, low, high);quickSort(arr, low, pivotIndex - 1); // 遞歸排序左子數組quickSort(arr, pivotIndex + 1, high); // 遞歸排序右子數組}}private static int partition(int[] arr, int low, int high) {int pivot = arr[high]; // 選擇最右元素作為基準int i = low - 1; // i是小于基準的元素的邊界for (int j = low; j < high; j++) {if (arr[j] < pivot) {i++;swap(arr, i, j); // 將小于基準的元素放到左側}}swap(arr, i + 1, high); // 將基準放到正確位置return i + 1;}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void main(String[] args) {int[] arr = {3, 6, 8, 10, 1, 2, 1};quickSort(arr, 0, arr.length - 1);System.out.println(Arrays.toString(arr)); // 輸出: [1, 1, 2, 3, 6, 8, 10]}
}
9、展示曾經寫過的項目代碼并講述功能
無
為什么選擇做安卓
我選擇做安卓開發的原因主要有以下幾點:
用戶基數大:Android 是全球市場份額最大的移動操作系統,擁有龐大的用戶群體。
開放性和靈活性:相比 iOS,Android 系統更開放,允許開發者更自由地定制和優化應用。
技術生態豐富:Android 開發涉及 UI/UX、性能優化、多線程、網絡通信等多個領域,技術挑戰性強。
跨平臺趨勢:Kotlin、Flutter、Jetpack Compose 等技術的發展讓 Android 開發更具擴展性。
此外,我對移動端交互和性能優化有濃厚興趣,Android 開發能讓我深入理解系統底層機制(如 Binder、Handler 等),提升綜合技術能力。
安卓了解多少,技術非技術都可以
技術方面
開發語言:Java(傳統)、Kotlin(官方推薦,更簡潔安全)。
核心組件:Activity(界面)、Service(后臺)、BroadcastReceiver(廣播)、ContentProvider(數據共享)。
UI 框架:XML + View 體系、Jetpack Compose(聲明式 UI)。
架構模式:MVC → MVP → MVVM(DataBinding + ViewModel + LiveData)。
性能優化:內存泄漏(LeakCanary)、卡頓分析(Systrace)、APK 瘦身(ProGuard)。
新技術:協程(Kotlin Flow)、KMM(跨平臺)、Android 12/13 新特性(如 Material You)。
非技術方面
市場現狀:Android 占據全球約 70% 移動市場份額,但國內廠商深度定制(如 MIUI、EMUI)。
開發者生態:Google Play 審核較寬松,但國內需適配各大應用商店。
挑戰:碎片化嚴重(系統版本、屏幕尺寸、廠商 ROM 差異)。
聊項目,登錄采用的redis+cookie的分布式session解決方案,具體聊聊
在分布式系統中,Session 需共享,避免用戶登錄狀態丟失(如服務器重啟或負載均衡切換)。
實現方案
登錄流程:
用戶輸入賬號密碼,服務端校驗通過后生成唯一?
SessionID
。將?
SessionID:UserInfo
?存入 Redis(設置過期時間)。通過?
Set-Cookie
?將?SessionID
?返回給瀏覽器。
后續請求:
瀏覽器自動攜帶?
Cookie(SessionID)
。服務端從 Redis 查詢?
SessionID
,獲取用戶信息。
安全性優化:
Cookie 設置?
HttpOnly
?防 XSS,Secure
?強制 HTTPS。Redis 存儲的 Session 可加密(如 JWT)。
優點
無狀態:服務端無需存儲 Session,適合橫向擴展。
高可用:Redis 集群保障 Session 不丟失。
登錄過程當中對密碼的校驗,存儲講講
校驗流程
前端對密碼做初步校驗(如長度、復雜度)。
服務端二次校驗(防惡意請求),例如:
if (password.length() < 8 || !containsLetterAndDigit(password)) {throw new InvalidPasswordException(); }
存儲方案
哈希加密:使用?
BCrypt
(推薦)或?PBKDF2
,避免明文存儲。String hashedPassword = BCrypt.hashpw(rawPassword, BCrypt.gensalt());
加鹽(Salt):防止彩虹表攻擊,每個用戶密碼使用獨立隨機鹽值。
面向對象的三大特性具體講解下
封裝(Encapsulation)
隱藏內部實現,暴露安全接口。
繼承(Inheritance)
子類復用父類屬性和方法(
extends
)。
多態(Polymorphism)
同一方法在不同子類中有不同實現(覆蓋?
@Override
?+ 父類引用指向子類對象)。
講講java的權限控制(protect繼承關系,default是包訪問權限)
修飾符 | 類內 | 同包 | 子類 | 其他包 |
---|---|---|---|---|
private | ? | ? | ? | ? |
default | ? | ? | ? | ? |
protected | ? | ? | ? | ? |
public | ? | ? | ? | ? |
protected
:子類可訪問(即使跨包)。default
(包權限):僅同包內可見。
java基本類型的以及占空間大小
類型 | 大小 | 取值范圍 |
---|---|---|
boolean | 1字節 | true /false |
byte | 1字節 | -128 ~ 127 |
short | 2字節 | -32768 ~ 32767 |
int | 4字節 | -231 ~ 231-1 |
long | 8字節 | -2?3 ~ 2?3-1 |
float | 4字節 | IEEE 754 單精度浮點 |
double | 8字節 | IEEE 754 雙精度浮點 |
char | 2字節 | Unicode 字符(0~65535) |
注意:JVM 可能對?
boolean
?優化為 1 bit,但數組中占 1 字節。
boolean類型占多大內存,int占多少,double(8字節)
如上
java循環的使用
(1)?for
?循環
(2)?while
?循環
(3)?do-while
?循環
(4) 增強?for
(遍歷集合)
java的反射機制,單例模式被反射機制破環,具體是反射的哪些Api進行破環的
Java 反射可以過?Class.getDeclaredConstructor()
?和?Constructor.setAccessible(true)
?繞過單例模式的私有構造方法限制,從而創建多個實例。
防御反射攻擊的方法
枚舉單例(推薦):JVM 保證枚舉實例的唯一性,反射無法破壞。
構造方法中拋出異常
簡單介紹單例模式的實現方式都有哪些
實現方式 | 特點 | 線程安全 | 防反射 |
---|---|---|---|
餓漢式 | 類加載時初始化,可能浪費資源 | ? | ? |
懶漢式 | 第一次調用時初始化,需加鎖解決線程問題 | ?(需同步) | ? |
雙重檢測鎖 | 延遲加載 + 同步塊優化性能 | ? | ? |
靜態內部類 | 利用類加載機制保證線程安全,延遲加載 | ? | ? |
枚舉 | 最安全,JVM 保障唯一性,天然防反射和序列化破壞 | ? | ? |
雙重檢測鎖的模式可以解決懶漢式單例的存在的多線程問題,請問枚舉可以解決單例模式存在的
單例模式的優勢
線程安全:JVM 在加載枚舉類時保證實例唯一。
防反射攻擊:
Constructor.newInstance()
?會直接拋出異常。防序列化破壞:枚舉的序列化由 JVM 特殊處理,不會創建新實例。
java當中的集合八股
集合框架分類
Collection
List
:有序可重復(ArrayList
、LinkedList
)。Set
:無序不重復(HashSet
、TreeSet
)。Queue
:隊列(LinkedList
、PriorityQueue
)。
Map
HashMap
:數組 + 鏈表/紅黑樹。TreeMap
:基于紅黑樹有序。ConcurrentHashMap
:線程安全。
高頻考點
ArrayList
?vs?LinkedList
HashMap
?的哈希沖突解決(拉鏈法 + 紅黑樹)。ConcurrentHashMap
?的分段鎖(JDK7)和 CAS + synchronized(JDK8)。
HashMap的擴容機制
觸發條件:當元素數量超過?
容量 × 負載因子(默認 0.75)
?時擴容。擴容過程:
新建一個 2 倍大小的數組。
重新計算每個鍵值對的哈希值,分配到新數組(JDK8 優化:高位掩碼判斷位置是否變化)。
JDK8 優化:鏈表長度 ≥8 時轉紅黑樹(提高查詢效率)。
Java多線程當中的鎖
鎖的分類
synchronized
修飾方法或代碼塊,JVM 級別實現。
可重入,非公平鎖。
ReentrantLock
API 級別鎖,需手動?
lock()
/unlock()
。支持公平鎖、可中斷、條件變量(
Condition
)。
ReadWriteLock
讀寫分離(
ReentrantReadWriteLock
),提高讀多寫少場景性能。
StampedLock
樂觀讀鎖,避免寫線程饑餓。
在項目當中使用過哪些鎖,怎么使用的
略
new對象的時候,JVM底層的一個過程(類加載機制)
當執行?new MyClass()
?時,JVM 底層會經歷以下步驟:
(1) 類加載(若未加載)
加載(Loading):
通過類加載器(
ClassLoader
)查找?.class
?文件,將字節碼加載到方法區。生成?
Class
?對象(存儲在堆中,作為方法區數據的訪問入口)。
驗證(Verification):檢查字節碼合法性(如魔數、語法)。
準備(Preparation):為靜態變量分配內存并賦默認值(如?
int
?初始化為?0
)。解析(Resolution):將符號引用(如類名、方法名)轉為直接引用(內存地址)。
初始化(Initialization):執行靜態代碼塊(
static{}
)和靜態變量賦值。
(2) 對象實例化
分配內存:
指針碰撞(堆內存規整時):移動指針分配連續空間。
空閑列表(堆內存不規整時):從空閑內存塊列表中選擇合適區域。
內存空間初始化:將所有字段置為默認值(如?
int
?為?0
,引用為?null
)。設置對象頭:存儲 Mark Word(哈希碼、GC 分代年齡等)和類元數據指針(指向方法區的?
Class
?對象)。執行構造方法(
<init>
):調用用戶定義的構造函數,完成字段賦值。
(3) 對象引用關聯
將堆中對象的內存地址賦給棧中的引用變量(如?
MyClass obj
)。
講講網絡當中Https
HTTPS = HTTP + SSL/TLS,核心是通過加密和證書保障安全:
(1) 加密流程(TLS 握手)
客戶端發起請求:
發送支持的加密算法列表和隨機數(Client Random)。
服務器響應:
返回選擇的加密算法、服務器證書(含公鑰)和隨機數(Server Random)。
證書驗證:
客戶端用 CA 機構的公鑰驗證證書合法性(防中間人攻擊)。
生成會話密鑰:
客戶端用服務器公鑰加密一個?Pre-Master Secret?并發送。
雙方通過?
Client Random + Server Random + Pre-Master
?生成對稱密鑰(Session Key)。
加密通信:
后續數據傳輸使用 Session Key 對稱加密(如 AES)。
(2) 關鍵點
非對稱加密:用于密鑰交換(RSA/ECDHE)。
對稱加密:用于數據傳輸(AES)。
數字證書:驗證服務器身份,由 CA 機構簽發。
剛剛提到的Https是基于Http,Http使用的是Tcp,那么Tcp的四次揮手當中第三次揮手是誰向誰進行揮手
在 TCP 四次揮手中:
第一次揮手:客戶端 → 服務器,發送?
FIN=1
(客戶端主動關閉)。第二次揮手:服務器 → 客戶端,發送?
ACK=1
(確認收到?FIN
)。第三次揮手:服務器 → 客戶端,發送?
FIN=1
(服務器準備關閉)。第四次揮手:客戶端 → 服務器,發送?
ACK=1
(確認收到?FIN
)。
關鍵問題答案:
第三次揮手是服務器向客戶端發送?
FIN
,表示服務器數據已發送完畢,準備關閉連接。
為什么需要四次揮手?
TCP 是全雙工的,雙方需獨立關閉自己的發送通道。
第二次和第三次揮手不能合并:服務器可能還有數據要發送(延遲確認)。
總結:
new
?對象過程:類加載 → 分配內存 → 初始化 → 構造方法調用。HTTPS:通過 TLS 握手建立安全通道,混合使用非對稱加密和對稱加密。
TCP 揮手:第三次揮手是服務器通知客戶端關閉連接。
數據結構當中棧和隊列在項目使用過嘛
略
算法題:兩個棧實現一個隊列
隊列(Queue)是?先進先出(FIFO)?的數據結構,而棧(Stack)是?后進先出(LIFO)?的數據結構。我們可以利用?兩個棧(stack1
?和?stack2
)?來模擬隊列的操作:
核心思想
入隊(
enqueue
):直接壓入?stack1
。出隊(
dequeue
):如果?
stack2
?為空,則把?stack1
?的所有元素彈出并壓入?stack2
(此時?stack2
?的棧頂就是最早入隊的元素)。如果?
stack2
?不為空,直接彈出棧頂元素。
.工作內容簡單介紹(10min)
略
2.介紹一下TCP三握四次揮手(10min)
三次握手(建立連接)
SYN(Client → Server):
客戶端發送?
SYN=1, seq=x
(隨機序列號)。
SYN+ACK(Server → Client):
服務端返回?
SYN=1, ACK=1, seq=y, ack=x+1
(確認客戶端的?x
,并發送自己的?y
)。
ACK(Client → Server):
客戶端發送?
ACK=1, seq=x+1, ack=y+1
(確認服務端的?y
)。
??目的:確保雙方都有發送和接收能力,防止歷史連接干擾。
四次揮手(關閉連接)
FIN(Client → Server):
客戶端發送?
FIN=1, seq=u
(表示不再發送數據)。
ACK(Server → Client):
服務端返回?
ACK=1, ack=u+1
(確認收到?FIN
)。
FIN(Server → Client):
服務端發送?
FIN=1, seq=v
(表示服務端也準備關閉)。
ACK(Client → Server):
客戶端返回?
ACK=1, ack=v+1
(確認服務端的?FIN
)。
??為什么需要四次?
TCP 是全雙工的,雙方需獨立關閉自己的發送通道。
2.1為什么第四次揮手要超時等待2MSL
MSL(Maximum Segment Lifetime):報文最大生存時間(Linux 默認 60s)。
目的 1:確保最后一個?
ACK
?能到達服務端。如果服務端沒收到?
ACK
,會重發?FIN
,客戶端在?2MSL
?內還能響應。
目的 2:讓本次連接的所有報文在網絡中消失,避免影響后續新連接。
2.2如果有大量的time_wait,close_wait,你會如何檢測分析,原因?出現階段?以及如何避免
(1)TIME_WAIT
(客戶端狀態)
出現階段:主動關閉連接的一方(如 HTTP 客戶端、微服務調用方)。
原因:
短連接頻繁建立和關閉(如爬蟲、API 頻繁調用)。
沒有復用 TCP 連接(如 HTTP/1.1 未啟用?
Keep-Alive
)。
解決:
復用連接(HTTP/1.1?
Keep-Alive
、連接池)。調整內核參數(慎用):
(2)CLOSE_WAIT
(服務端狀態)
出現階段:被動關閉連接的一方(如服務端未正確調用?
close()
)。原因:
代碼 Bug:未關閉 Socket(如 Java 未調用?
socket.close()
)。線程阻塞:處理請求時卡住,無法執行關閉邏輯。
解決:
檢查代碼確保資源釋放(
try-with-resources
?或?finally
?塊)。優化服務端性能(避免阻塞)。
2.3什么情況下syn請求丟棄,失效?如何分析,如何解決,不考慮防火墻
(1)SYN 被丟棄的原因
半連接隊列(SYN Queue)滿:
服務端未及時處理?
SYN
,導致隊列溢出(默認大小?net.ipv4.tcp_max_syn_backlog
)。
SYN Flood 攻擊:
攻擊者發送大量?
SYN
?但不完成握手,耗盡服務端資源。
網絡問題:
中間路由器丟棄?
SYN
(如擁塞、TTL 過期)。
(2)如何分析?
服務端統計:
抓包分析:
(3)解決方案
增大半連接隊列:
啟用 SYN Cookie(防攻擊):
優化服務端:
加快握手處理(如負載均衡、擴容)。
總結
問題 | 原因 | 解決方案 |
---|---|---|
TIME_WAIT ?過多 | 短連接頻繁關閉 | 復用連接、調整?tcp_tw_reuse |
CLOSE_WAIT ?過多 | 服務端未正確關閉 Socket | 檢查代碼、優化資源釋放 |
SYN 被丟棄 | 隊列滿、攻擊、網絡問題 | 增大隊列、SYN Cookie、抓包分析 |
3.項目深挖,包括項目實現背景(即為什么去做這個項目),項目功能如何實現,項目實現中的一些細節和設計模式,項目對應功能如何測試,如何部署。遇到問題如何發散解決(40min)
略
3.進程線程區別
對比項 | 進程(Process) | 線程(Thread) |
---|---|---|
定義 | 操作系統資源分配的基本單位 | CPU 調度的基本單位(屬于進程) |
內存占用 | 獨立內存空間(隔離性強) | 共享進程內存(高效但需同步) |
創建開銷 | 大(需分配獨立資源) | 小(共享進程資源) |
通信方式 | 進程間通信(IPC):管道、共享內存、消息隊列 | 直接讀寫共享變量(需加鎖) |
崩潰影響 | 一個進程崩潰不影響其他進程 | 一個線程崩潰可能導致整個進程退出 |
并發性 | 多進程并行(多核) | 多線程并行(輕量級并發) |
關鍵點:
線程是進程的子任務,共享進程的堆內存,但有自己的棧和寄存器。
多線程需處理競態條件(如?
synchronized
、ReentrantLock
)。
4OSI七層模型
層數 | 名稱 | 功能 | 協議/設備 |
---|---|---|---|
7 | 應用層 | 用戶接口(HTTP、FTP) | HTTP、SMTP、DNS |
6 | 表示層 | 數據格式轉換(加密、壓縮) | SSL、JPEG |
5 | 會話層 | 建立/管理會話(RPC) | NetBIOS |
4 | 傳輸層 | 端到端可靠傳輸(TCP/UDP) | TCP、UDP |
3 | 網絡層 | 路由尋址(IP 地址) | IP、ICMP、路由器 |
2 | 數據鏈路層 | 幀傳輸(MAC 地址) | Ethernet、交換機 |
1 | 物理層 | 比特流傳輸(電纜、光纖) | 網卡、集線器 |
簡化記憶:
上三層(應用、表示、會話):面向用戶。
下四層(傳輸、網絡、數據鏈路、物理):面向數據。
5詳細介紹線程
線程的生命周期(狀態)
NEW:剛創建,未調用?
start()
。RUNNABLE:可運行(可能在等待 CPU)。
BLOCKED:等待鎖(如?
synchronized
)。WAITING:無限期等待(如?
wait()
)。TIMED_WAITING:超時等待(如?
sleep(1000)
)。TERMINATED:執行完畢。
創建線程的方式
繼承?
Thread
?類:實現?
Runnable
?接口:線程池(
ExecutorService
):
線程同步
synchronized
:ReentrantLock
:
1.get和post的區別
1. GET vs POST 的區別
對比項 | GET | POST |
---|---|---|
語義 | 獲取資源(冪等) | 提交數據(非冪等) |
數據位置 | URL 查詢參數(明文) | 請求體(可加密) |
長度限制 | 受 URL 長度限制(約 2KB) | 無限制(服務器可配置) |
緩存 | 可被緩存 | 不可緩存 |
安全性 | 參數暴露在 URL(不安全) | 數據在請求體中(相對安全) |
使用場景:
GET:搜索、分頁(如?
?page=1
)。POST:登錄、表單提交(如 JSON 數據)。
5.互聯網這兩年前景不好,談一下你的看法
短期挑戰:
政策監管加強(如數據安全、反壟斷)。
資本趨于理性,野蠻增長時代結束。
全球經濟下行影響投資和消費。
長期機會:
技術驅動:AI、云計算、物聯網等仍是未來核心。
數字化轉型:傳統行業(醫療、制造)仍需互聯網技術賦能。
全球化市場:中國互聯網企業出海(如 TikTok、SHEIN)。
結論:行業從“高速增長”轉向“高質量發展”,對技術深度和復合能力要求更高。
6.為什么覺著互聯網會比其他行業就業廣
技術滲透性強:
幾乎所有行業都需要互聯網技術(金融→FinTech、零售→電商)。
崗位多樣性:
技術(開發、測試)、產品、運營、設計、數據分析等崗位覆蓋全鏈條。
薪資競爭力:
平均薪資高于傳統行業(如制造業)。
低準入門檻:
相比醫生、律師等職業,互聯網更依賴技能而非學歷證書。
遠程辦公機會:
支持全球化協作(如程序員可遠程為海外公司工作)。
7.app測試和web測試有何不同
對比項 | App 測試 | Web 測試 |
---|---|---|
運行環境 | 移動設備(iOS/Android) | 瀏覽器(Chrome、Firefox) |
兼容性 | 需測試不同機型、OS版本、分辨率 | 主要測試瀏覽器兼容性 |
網絡依賴 | 弱網、斷網測試更重要 | 網絡影響較小 |
安裝與更新 | 需測試安裝、升級、卸載流程 | 無需安裝,即時更新 |
性能指標 | 內存占用、CPU、電量、啟動速度 | 頁面加載速度、服務器響應時間 |
工具 | Appium、XCUITest、Espresso | Selenium、Cypress、Playwright |
核心差異:
App 測試更關注硬件交互(如攝像頭、GPS)和移動端特性(如手勢操作)。
Web 測試更注重跨瀏覽器一致性和前端渲染性能。
8.你是怎么區分前端和后端的
對比項 | 前端(Frontend) | 后端(Backend) |
---|---|---|
職責 | 用戶界面(UI)和交互邏輯 | 數據處理、業務邏輯、數據庫交互 |
技術棧 | HTML/CSS/JavaScript、React/Vue | Java/Python/Go、Spring/Django |
關注點 | 用戶體驗、頁面性能、兼容性 | 高并發、安全性、API 設計 |
調試工具 | Chrome DevTools、Lighthouse | Postman、Jmeter、日志分析 |
輸出結果 | 瀏覽器渲染的頁面 | 數據庫記錄、API 響應(JSON/XML) |
簡單判斷:
前端代碼運行在瀏覽器,后端代碼運行在服務器。
前端請求數據(如?
fetch('/api/data')
),后端提供數據(如返回?JSON
)。
內存分頁與分段的區別及優缺點
分頁(Paging)
原理:
內存劃分為固定大小的頁(如 4KB),進程的地址空間分為同等大小的頁框。
通過頁表映射虛擬地址到物理地址。
優點:
解決外部碎片(物理內存利用率高)。
支持虛擬內存(頁面可換入換出磁盤)。
缺點:
頁內可能產生內部碎片(最后一頁未用滿)。
分段(Segmentation)
原理:
按邏輯單元(代碼段、數據段、堆棧段)劃分內存,每段長度可變。
通過段表記錄基址和長度。
優點:
符合程序邏輯(便于共享和保護段)。
缺點:
產生外部碎片(需內存緊湊或動態分區)。
對比總結
特性 | 分頁 | 分段 |
---|---|---|
劃分單位 | 固定大小頁 | 可變長度段 |
碎片問題 | 內部碎片 | 外部碎片 |
管理復雜度 | 簡單(頁表) | 復雜(段表+保護機制) |
適用場景 | 通用內存管理(OS 主流方案) | 需要邏輯隔離(如早期系統) |
現代 OS(如 Linux):結合分頁和分段,實際使用分頁機制,段基址固定為 0。
Android方向
四大組件生命周期(Activity、Service等)
(1) Activity 生命周期
核心方法:
onCreate()
:初始化 UI 和數據。onStart()
:Activity 可見但未前臺交互。onResume()
:Activity 進入前臺,可交互。onPause()
:失去焦點(如彈窗),需快速釋放資源。onStop()
:完全不可見(可能被銷毀)。onDestroy()
:釋放所有資源。
場景:
屏幕旋轉:
onDestroy()
?→?onCreate()
(默認重建)。按 Home 鍵:
onPause()
?→?onStop()
。
(2) Service 生命周期
啟動方式:
startService()
:onCreate()
?→?onStartCommand()
?→ (運行中)→?onDestroy()
。
bindService()
:onCreate()
?→?onBind()
?→ (通信中)→?onUnbind()
?→?onDestroy()
。
(3) BroadcastReceiver
動態注冊:
onReceive()
?執行后立即銷毀。
靜態注冊:
常駐,通過 AndroidManifest.xml 聲明。
(4) ContentProvider
生命周期由系統管理,主要方法:
onCreate()
:初始化數據源(如數據庫)。query()
/insert()
/update()
/delete()
:CRUD 操作。
Handler機制原理(Looper、MessageQueue)
核心組件
Handler
:發送和處理消息(sendMessage()
?/?handleMessage()
)。MessageQueue
:消息隊列(單鏈表,按時間排序)。Looper
:循環從?MessageQueue
?取消息并分發。
工作流程
Looper.prepare():創建?
Looper
?和?MessageQueue
(主線程已默認創建)。Looper.loop():無限循環調用?
MessageQueue.next()
?獲取消息。Handler.sendMessage():將?
Message
?插入?MessageQueue
。Handler.handleMessage():在目標線程處理消息。
性能優化:內存泄漏(Cursor未關閉、Bitmap未回收)、ANR原因
自定義View流程(measure/layout/draw)
iOS方向
Runtime機制:消息轉發、Category實現
消息轉發
Objective-C 的消息轉發機制是在對象無法響應某個方法時提供的一種補救措施。消息轉發分為三個階段:
動態方法解析:
+resolveInstanceMethod:
?或?+resolveClassMethod:
,可以在這里動態添加方法實現。備用接收者:
-forwardingTargetForSelector:
,可以將消息轉發給其他對象處理。完整轉發:
-methodSignatureForSelector:
?和?-forwardInvocation:
,可以封裝 NSInvocation 進行更靈活的轉發。
Category 實現
Category 是通過運行時動態將方法添加到類中(編譯時為類生成 category_t 結構體,運行時合并到類的方法列表中)。特點:
可以添加方法,但不能添加實例變量(可通過關聯對象間接實現)。
方法會覆蓋原類方法(同名方法調用優先級:Category > 原類 > 父類)。
實現原理:
編譯后生成?
_category_t
?結構體,包含方法、屬性、協議列表。運行時通過?
attachCategories
?函數將 Category 數據合并到類中。
多線程:GCD與NSOperation對比、線程安全
特性 | GCD (Grand Central Dispatch) | NSOperation |
---|---|---|
抽象層級 | C API,更底層 | Objective-C 對象,更高層 |
任務封裝 | Block | NSOperation 子類 |
依賴管理 | 需手動控制(如 barrier) | 直接通過?addDependency: ?支持 |
狀態控制 | 無直接狀態管理 | 可監聽 isReady/isFinished/isCancelled |
優先級 | 通過 QoS 設置 | 可設置 queuePriority |
取消任務 | 不可取消 | 可取消 |
適用場景 | 簡單異步任務 | 復雜任務依賴關系 |
線程安全
保證線程安全的常見方式:
串行隊列:將讀寫操作放到同一隊列(如?
dispatch_queue_serial
)。鎖:
@synchronized
、NSLock
、os_unfair_lock
、pthread_mutex
。原子操作:
atomic
?屬性(僅保證讀寫原子性,不保證線程安全)。內存屏障:
OSMemoryBarrier
?避免指令重排。
設計模式:Delegate vs Notification vs KVO的差異及應用場景
特性 | Delegate | Notification | KVO |
---|---|---|---|
通信方向 | 一對一(反向傳值) | 一對多(廣播) | 一對多(監聽屬性變化) |
耦合度 | 較高(需協議綁定) | 低(松散耦合) | 最低(無需顯式調用) |
實現復雜度 | 中(需實現協議方法) | 低(僅注冊觀察) | 高(需處理移除觀察者) |
適用場景 | UITableView 事件處理 | 跨模塊通信(如登錄狀態廣播) | 數據模型變化監聽(如進度更新) |
性能開銷 | 低(直接調用) | 中(需維護觀察者列表) | 高(依賴 Runtime 派發) |
最佳實踐:
需要返回值時用 Delegate。
跨組件通信用 Notification。
監聽對象屬性變化用 KVO(注意移除觀察者避免崩潰)。
單例模式的實現與優缺點
優點
全局唯一訪問點,便于管理資源(如配置、緩存)。
減少重復實例化開銷。
缺點
測試困難:全局狀態可能導致測試依賴。
內存常駐:單例生命周期與應用一致。
隱藏耦合:濫用會導致代碼難以維護。
替代方案:依賴注入(通過參數傳遞實例)。
MVC/MVVM在Android中的實踐
MVC
Model:數據層(Room、Retrofit)。
View:XML 布局文件。
Controller:Activity/Fragment(實際中常承擔過多邏輯)。
問題:Activity 臃腫,單元測試困難。
MVVM(推薦)
ViewModel:持有數據,暴露 LiveData/Flow。
View:Activity/Fragment 觀察數據變化。
Data Binding:可選的 XML 綁定(減少樣板代碼)。