戰(zhàn)路徑)
簡(jiǎn)介這份Java高頻面試題PDF面向準(zhǔn)備Java后端崗位面試的求職者與初中級(jí)開(kāi)發(fā)者聚焦Spring生態(tài)與數(shù)據(jù)庫(kù)調(diào)優(yōu)兩大高頻考點(diǎn)。內(nèi)容系統(tǒng)梳理了Spring Bean生命周期實(shí)例化、依賴(lài)注入、初始化、銷(xiāo)毀、Spring MVC完整執(zhí)行流程、Spring Boot自動(dòng)裝配原理以及SQL執(zhí)行計(jì)劃解讀、索引失效場(chǎng)景與優(yōu)化技巧、MySQL常見(jiàn)索引類(lèi)型和B樹(shù)底層結(jié)構(gòu)并延伸至線(xiàn)程池種類(lèi)與核心參數(shù)、拒絕策略等并發(fā)知識(shí)點(diǎn)。資源包共1個(gè)PDF文件約396KB輕量便攜適合碎片化復(fù)習(xí)與面試前速查。目前已有180人學(xué)習(xí)瀏覽。讀者可借此快速串聯(lián)Spring框架核心機(jī)制與SQL優(yōu)化思路對(duì)照?qǐng)?zhí)行計(jì)劃字段與索引失效清單查漏補(bǔ)缺形成結(jié)構(gòu)化的面試答題框架提升技術(shù)表達(dá)與實(shí)戰(zhàn)應(yīng)對(duì)能力。1. 從一份 Java 高頻面試題 PDF 說(shuō)起為什么背完答案還是掛面試間里最尷尬的場(chǎng)景不是被問(wèn)到完全沒(méi)聽(tīng)過(guò)的名詞而是題目你見(jiàn)過(guò)、答案你背過(guò)面試官追問(wèn)一句“為什么”就卡殼。很多人手里都有一份流傳的 Java 高頻面試題 PDF幾百道題、分類(lèi)清晰、答案現(xiàn)成看起來(lái)是捷徑實(shí)際用起來(lái)卻像黑匣子——輸入題目、輸出答案中間的理解過(guò)程被跳過(guò)了。這份 PDF 真正該被當(dāng)成什么不是背誦手冊(cè)而是一張知識(shí)地圖的索引。它告訴你哪些點(diǎn)會(huì)被反復(fù)考但每個(gè)點(diǎn)背后的原理、邊界、版本差異得自己補(bǔ)上。這篇文章面向正在準(zhǔn)備 Java 后端面試的開(kāi)發(fā)者尤其是工作一到三年、想從“會(huì)寫(xiě)業(yè)務(wù)代碼”跨到“能講清底層機(jī)制”的人。我會(huì)把這份高頻題 PDF 拆成可復(fù)現(xiàn)的學(xué)習(xí)路徑哪些題必須手寫(xiě)代碼驗(yàn)證、哪些參數(shù)要親手調(diào)一遍、哪些坑是面試官最?lèi)?ài)追問(wèn)的。目標(biāo)很直接——讓你下次被追問(wèn)時(shí)能順著原理往下講三層而不是背完第一層就沒(méi)了。2. 把高頻題 PDF 拆成可執(zhí)行的知識(shí)模塊先分類(lèi)再動(dòng)手拿到一份 Java 高頻面試題 PDF第一反應(yīng)不該是從第一頁(yè)開(kāi)始背。我一般會(huì)先做一次結(jié)構(gòu)拆解把題目按“考察層次”重新歸類(lèi)因?yàn)椴煌瑢哟蔚念}準(zhǔn)備方式完全不同。PDF 的原始分類(lèi)通常是按知識(shí)點(diǎn)排的——集合、并發(fā)、JVM、Spring、數(shù)據(jù)庫(kù)——但面試官提問(wèn)時(shí)是混合著來(lái)的所以你得自己建一套索引。2.1 按考察層次給題目打標(biāo)簽記憶層、原理層、設(shè)計(jì)層記憶層的題答案是事實(shí)性的比如“HashMap 默認(rèn)容量是多少”“ArrayList 和 LinkedList 的區(qū)別”。這類(lèi)題占比不小但單獨(dú)背它們性?xún)r(jià)比最低因?yàn)槊嬖嚬俸苌僦粏?wèn)事實(shí)一定會(huì)往原理層追。原理層的題問(wèn)的是“為什么這樣設(shè)計(jì)”比如“HashMap 為什么用紅黑樹(shù)而不是 AVL”“ConcurrentHashMap 為什么在 JDK 8 改成 CAS synchronized”。設(shè)計(jì)層的題最開(kāi)放比如“讓你設(shè)計(jì)一個(gè)本地緩存你會(huì)考慮哪些點(diǎn)”它考的是你把前面兩層串起來(lái)的能力。我的做法是給 PDF 里每道題標(biāo)一個(gè)層級(jí)然后統(tǒng)計(jì)比例。如果原理層和設(shè)計(jì)層的題加起來(lái)不到一半說(shuō)明這份 PDF 偏基礎(chǔ)你得自己補(bǔ)深度如果超過(guò)七成那它更適合當(dāng)復(fù)習(xí)提綱而不是入門(mén)材料。這個(gè)判斷決定了你后面花多少時(shí)間在動(dòng)手驗(yàn)證上。2.2 用最小代碼驗(yàn)證記憶層結(jié)論以 HashMap 擴(kuò)容為例記憶層的結(jié)論最容易記錯(cuò)也最容易被追問(wèn)翻車(chē)。與其死記不如寫(xiě)一段最小代碼跑一遍。下面這段代碼用來(lái)觀(guān)察 HashMap 的擴(kuò)容時(shí)機(jī)和容量變化注意我加了反射讀取內(nèi)部閾值這是理解擴(kuò)容邏輯的關(guān)鍵。import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; public class HashMapProbe { public static void main(String[] args) throws Exception { MapString, Integer map new HashMap(); // 反射拿到 table 和 threshold 字段觀(guān)察擴(kuò)容 Field tableField HashMap.class.getDeclaredField(table); tableField.setAccessible(true); Field thresholdField HashMap.class.getDeclaredField(threshold); thresholdField.setAccessible(true); for (int i 0; i 20; i) { map.put(key i, i); Object[] table (Object[]) tableField.get(map); int threshold (int) thresholdField.get(map); int capacity table null ? 0 : table.length; System.out.printf(size%d, capacity%d, threshold%d%n, map.size(), capacity, threshold); } } }這段代碼的邏輯說(shuō)明HashMap 在第一次 put 時(shí)才初始化 table默認(rèn)容量 16、負(fù)載因子 0.75所以閾值是 12。當(dāng) size 超過(guò)閾值時(shí)觸發(fā)擴(kuò)容容量翻倍閾值也翻倍。運(yùn)行后你會(huì)看到 capacity 從 0 跳到 16再到 32threshold 從 0 到 12 再到 24。參數(shù)說(shuō)明負(fù)載因子 0.75 是空間和時(shí)間的折中調(diào)大減少擴(kuò)容但增加哈希沖突調(diào)小相反初始容量如果提前知道數(shù)據(jù)量應(yīng)該設(shè)為預(yù)期元素?cái)?shù) / 0.75 1避免多次擴(kuò)容。這個(gè)結(jié)論背下來(lái)只要一句話(huà)但親手跑一遍面試官問(wèn)“為什么是 0.75”時(shí)你就能從泊松分布和沖突概率的角度答而不是說(shuō)“書(shū)上寫(xiě)的”。2.3 給并發(fā)題建一張參數(shù)對(duì)照表synchronized 與 ReentrantLock并發(fā)是高頻題里最容易答得含糊的部分。我習(xí)慣把關(guān)鍵類(lèi)做成對(duì)照表面試前掃一遍比背大段文字有效。下面這張表覆蓋了最常被對(duì)比的兩個(gè)鎖參數(shù)和邊界都列清楚。對(duì)比項(xiàng)synchronizedReentrantLock鎖獲取方式JVM 內(nèi)置自動(dòng)釋放顯式 lock/unlock需 finally 釋放可中斷不支持lockInterruptibly 支持超時(shí)獲取不支持tryLock(timeout) 支持公平鎖非公平可選公平/非公平條件變量wait/notify 單一可創(chuàng)建多個(gè) Condition鎖升級(jí)偏向鎖→輕量級(jí)→重量級(jí)無(wú)升級(jí)概念基于 AQS這張表不是讓你背而是讓你在回答時(shí)能快速定位差異點(diǎn)。比如面試官問(wèn)“什么時(shí)候用 ReentrantLock”你就能從可中斷、超時(shí)、多條件三個(gè)場(chǎng)景切入而不是籠統(tǒng)說(shuō)“更靈活”。參數(shù)上要特別注意ReentrantLock 的公平鎖會(huì)降低吞吐非公平鎖可能造成線(xiàn)程饑餓默認(rèn)非公平是有性能考慮的。這些邊界在 PDF 的答案里往往只有一句話(huà)但面試官追問(wèn)時(shí)就是分水嶺。3. 用 JVM 和并發(fā)兩條線(xiàn)串起 PDF 里的硬骨頭高頻題 PDF 里真正拉開(kāi)差距的是 JVM 和并發(fā)這兩塊。它們題目多、追問(wèn)深、光靠背結(jié)論必翻車(chē)。我的策略是各選一條主線(xiàn)把零散的題掛上去形成能自己推演的鏈條。3.1 JVM 內(nèi)存結(jié)構(gòu)從一道“對(duì)象在哪分配”追到逃逸分析PDF 里常有一道題“對(duì)象一定分配在堆上嗎”標(biāo)準(zhǔn)答案是不一定可能棧上分配。但面試官接著會(huì)問(wèn)“什么情況下棧上分配”這就到了逃逸分析。要講清楚這條鏈得先理清 JVM 內(nèi)存結(jié)構(gòu)程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧、堆、方法區(qū)JDK 8 后是元空間。對(duì)象分配的主戰(zhàn)場(chǎng)是堆但 JIT 編譯器在逃逸分析后可能做標(biāo)量替換把對(duì)象拆成基本類(lèi)型放在棧上。驗(yàn)證這件事需要?jiǎng)邮终{(diào)參數(shù)。下面這組 JVM 參數(shù)用來(lái)觀(guān)察逃逸分析的效果注意-XX:PrintEscapeAnalysis在部分版本需要 debug 版 JVM生產(chǎn)環(huán)境一般用-XX:DoEscapeAnalysis開(kāi)啟即可。# 開(kāi)啟逃逸分析關(guān)閉標(biāo)量替換做對(duì)比 java -XX:DoEscapeAnalysis -XX:-EliminateAllocations -Xmx256m -jar demo.jar # 開(kāi)啟逃逸分析并允許標(biāo)量替換 java -XX:DoEscapeAnalysis -XX:EliminateAllocations -Xmx256m -jar demo.jar邏輯說(shuō)明DoEscapeAnalysis控制是否做逃逸分析EliminateAllocations控制是否允許標(biāo)量替換。兩個(gè)都開(kāi)時(shí)未逃逸的對(duì)象可能被拆散分配在棧上減少堆壓力。參數(shù)說(shuō)明-Xmx256m限制堆大小方便觀(guān)察 GC 頻率變化如果對(duì)象確實(shí)逃逸了比如被返回或存入全局集合逃逸分析不會(huì)生效這時(shí)調(diào)參也沒(méi)用。常見(jiàn)誤用是以為開(kāi)了逃逸分析所有對(duì)象就上棧實(shí)際上它只對(duì)未逃逸的局部對(duì)象生效而且受 JIT 編譯閾值影響方法得被調(diào)用足夠多次才會(huì)觸發(fā)優(yōu)化。面試時(shí)能講清“逃逸分析是 JIT 的優(yōu)化手段不是 JVM 規(guī)范強(qiáng)制”就已經(jīng)超過(guò)大多數(shù)候選人了。3.2 并發(fā)工具類(lèi)用 CountDownLatch 和 CyclicBarrier 做對(duì)照實(shí)驗(yàn)并發(fā)題里 CountDownLatch 和 CyclicBarrier 經(jīng)常被放在一起問(wèn)很多人背了“一個(gè)減一個(gè)加”就完事但面試官會(huì)追問(wèn)使用場(chǎng)景和異常處理。我一般寫(xiě)兩個(gè)最小 Demo 跑一遍把行為差異刻進(jìn)記憶。import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; public class LatchVsBarrier { public static void main(String[] args) throws Exception { // CountDownLatch主線(xiàn)程等 3 個(gè)子任務(wù)完成 CountDownLatch latch new CountDownLatch(3); for (int i 0; i 3; i) { new Thread(() - { try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println(Thread.currentThread().getName() done); latch.countDown(); }).start(); } latch.await(); System.out.println(all tasks finished); // CyclicBarrier3 個(gè)線(xiàn)程互相等待到齊后繼續(xù) CyclicBarrier barrier new CyclicBarrier(3, () - System.out.println(barrier action executed)); for (int i 0; i 3; i) { new Thread(() - { try { System.out.println(Thread.currentThread().getName() waiting); barrier.await(); System.out.println(Thread.currentThread().getName() passed); } catch (Exception e) { Thread.currentThread().interrupt(); } }).start(); } } }邏輯說(shuō)明CountDownLatch 是一次性的計(jì)數(shù)減到零后所有 await 的線(xiàn)程被釋放主線(xiàn)程繼續(xù)CyclicBarrier 是可循環(huán)的每個(gè)線(xiàn)程 await 后等其他人到齊然后一起繼續(xù)還能指定到齊后執(zhí)行的動(dòng)作。參數(shù)說(shuō)明CountDownLatch 的構(gòu)造參數(shù)是計(jì)數(shù)初始值必須和任務(wù)數(shù)一致調(diào)大了會(huì)永久阻塞CyclicBarrier 的構(gòu)造參數(shù)是參與線(xiàn)程數(shù)如果某個(gè)線(xiàn)程在 await 前拋異常其他線(xiàn)程會(huì)收到 BrokenBarrierException這是排查時(shí)最常忽略的點(diǎn)。常見(jiàn)誤用是把 CyclicBarrier 當(dāng) CountDownLatch 用結(jié)果發(fā)現(xiàn)它不能“一個(gè)線(xiàn)程等多個(gè)”因?yàn)樗腔ハ嗟?。面試時(shí)能說(shuō)出“CyclicBarrier 的 await 會(huì)拋 BrokenBarrierException需要處理”就是加分項(xiàng)。3.3 線(xiàn)程池參數(shù)把 PDF 里的七個(gè)參數(shù)落到一次壓測(cè)里線(xiàn)程池的七個(gè)參數(shù)幾乎每份 PDF 都有但背下來(lái)和會(huì)調(diào)是兩回事。核心線(xiàn)程數(shù)、最大線(xiàn)程數(shù)、空閑時(shí)間、時(shí)間單位、阻塞隊(duì)列、線(xiàn)程工廠(chǎng)、拒絕策略這七個(gè)里最容易翻車(chē)的是隊(duì)列和拒絕策略的組合。我一般用一段代碼模擬任務(wù)提交觀(guān)察不同隊(duì)列下的行為。import java.util.concurrent.*; public class PoolProbe { public static void main(String[] args) { // 核心 2最大 4隊(duì)列容量 2觀(guān)察拒絕時(shí)機(jī) ThreadPoolExecutor pool new ThreadPoolExecutor( 2, 4, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue(2), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); for (int i 0; i 10; i) { final int id i; try { pool.execute(() - { System.out.println(task id running on Thread.currentThread().getName()); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } catch (RejectedExecutionException e) { System.out.println(task id rejected); } } pool.shutdown(); } }邏輯說(shuō)明任務(wù)提交時(shí)先看核心線(xiàn)程是否滿(mǎn)沒(méi)滿(mǎn)就新建核心線(xiàn)程核心滿(mǎn)了進(jìn)隊(duì)列隊(duì)列滿(mǎn)了看最大線(xiàn)程是否滿(mǎn)沒(méi)滿(mǎn)就新建非核心線(xiàn)程都滿(mǎn)了觸發(fā)拒絕策略。參數(shù)說(shuō)明ArrayBlockingQueue(2)容量為 2所以前 2 個(gè)任務(wù)占核心線(xiàn)程第 3、4 個(gè)進(jìn)隊(duì)列第 5、6 個(gè)占最大線(xiàn)程第 7 個(gè)開(kāi)始被拒絕。如果把隊(duì)列換成LinkedBlockingQueue無(wú)界隊(duì)列最大線(xiàn)程數(shù)就永遠(yuǎn)不會(huì)被觸發(fā)任務(wù)會(huì)一直堆積直到 OOM這是生產(chǎn)環(huán)境最常見(jiàn)的坑。拒絕策略里 AbortPolicy 拋異常CallerRunsPolicy 讓提交線(xiàn)程自己跑DiscardPolicy 靜默丟棄DiscardOldestPolicy 丟最老的。面試時(shí)能說(shuō)清“無(wú)界隊(duì)列會(huì)讓 maximumPoolSize 失效”比背七個(gè)參數(shù)名字有用得多。4. 避坑與排查高頻題準(zhǔn)備里最容易翻車(chē)的五件事準(zhǔn)備 Java 面試的過(guò)程中有些坑幾乎每個(gè)人都會(huì)踩而且踩了之后還以為是題目太難。下面這五條是我自己和身邊人反復(fù)驗(yàn)證過(guò)的按“現(xiàn)象→原因→解決”寫(xiě)清楚。4.1 現(xiàn)象答案背得滾瓜爛熟一追問(wèn)就斷片原因記憶層和原理層混在一起背沒(méi)有建立因果鏈。PDF 的答案往往是結(jié)論式的比如“HashMap 線(xiàn)程不安全”但沒(méi)告訴你為什么不安全、什么場(chǎng)景下會(huì)出問(wèn)題。解決每背一個(gè)結(jié)論強(qiáng)制自己?jiǎn)柸齻€(gè)“為什么”然后寫(xiě)最小代碼驗(yàn)證。比如“線(xiàn)程不安全”就去跑多線(xiàn)程 put觀(guān)察死循環(huán)或數(shù)據(jù)丟失親手復(fù)現(xiàn)一次比背十遍都牢。4.2 現(xiàn)象JVM 參數(shù)題答得頭頭是道實(shí)際調(diào)優(yōu)時(shí)不敢下手原因參數(shù)是背的沒(méi)在真實(shí)或模擬環(huán)境里調(diào)過(guò)。比如-Xmn設(shè)多大、-XX:SurvivorRatio怎么算光看公式記不住。解決本地起一個(gè) Spring Boot 小服務(wù)用-Xmx256m -Xmn128m跑一遍再用jstat -gc觀(guān)察 Eden、Survivor、Old 區(qū)的變化把參數(shù)和 GC 日志對(duì)應(yīng)起來(lái)。參數(shù)說(shuō)明jstat -gc pid 1000每秒打印一次重點(diǎn)看 YGC 頻率和 FGC 次數(shù)如果 FGC 頻繁且每次回收不多多半是內(nèi)存泄漏或老年代太小。4.3 現(xiàn)象并發(fā)題一寫(xiě)代碼就出 bug面試手寫(xiě)環(huán)節(jié)翻車(chē)原因平時(shí)只看不寫(xiě)對(duì) API 的異常和邊界不熟。比如wait()必須在循環(huán)里調(diào)用、CountDownLatch.await()要處理中斷。解決把 PDF 里所有涉及手寫(xiě)的題列出來(lái)每道題在 IDE 里敲一遍跑通再關(guān)掉答案重寫(xiě)。重點(diǎn)練生產(chǎn)者消費(fèi)者、單例雙重檢查、線(xiàn)程交替打印這三類(lèi)它們覆蓋了鎖、等待通知、內(nèi)存可見(jiàn)性的核心。4.4 現(xiàn)象Spring 題答成配置背誦被問(wèn)原理就轉(zhuǎn)移話(huà)題原因把 Spring 當(dāng)黑盒用沒(méi)理解 IoC 和 AOP 的實(shí)現(xiàn)。解決寫(xiě)一個(gè)最小的 IoC 容器用反射和注解實(shí)現(xiàn) bean 的掃描、實(shí)例化、注入幾十行代碼就能跑通。AOP 則用 JDK 動(dòng)態(tài)代理和 CGLIB 各寫(xiě)一個(gè) Demo對(duì)比兩者的區(qū)別。參數(shù)說(shuō)明JDK 動(dòng)態(tài)代理要求目標(biāo)類(lèi)實(shí)現(xiàn)接口CGLIB 通過(guò)繼承實(shí)現(xiàn)所以 final 類(lèi)無(wú)法被 CGLIB 代理這是面試常問(wèn)的邊界。4.5 現(xiàn)象數(shù)據(jù)庫(kù)題只答索引原理不會(huì)看執(zhí)行計(jì)劃原因索引結(jié)構(gòu)背得熟但沒(méi)在真實(shí)查詢(xún)里用過(guò)EXPLAIN。解決建一張百萬(wàn)級(jí)的模擬表對(duì)同一個(gè)查詢(xún)分別加索引和不加索引用EXPLAIN看 type、key、rows 的變化。重點(diǎn)理解 type 從 ALL 到 ref 到 const 的差別以及最左前綴原則在聯(lián)合索引里的體現(xiàn)。參數(shù)說(shuō)明EXPLAIN的 rows 是預(yù)估掃描行數(shù)不是精確值但數(shù)量級(jí)能反映索引是否生效如果 type 是 ALL 且 rows 很大說(shuō)明走了全表掃描需要檢查索引列和查詢(xún)條件是否匹配。5. 從背題到能講用費(fèi)曼技巧把 PDF 榨干最后一章說(shuō)一個(gè)我反復(fù)用、也確實(shí)有效的技巧把 PDF 里的每道高頻題當(dāng)成你要講給一個(gè)剛?cè)胄械耐侣?tīng)。費(fèi)曼技巧的核心不是復(fù)述而是用最少的術(shù)語(yǔ)把因果講通講不通的地方就是你的知識(shí)缺口。具體做法是挑一道題比如“ThreadLocal 為什么會(huì)內(nèi)存泄漏”先合上 PDF用白板或空白文檔寫(xiě)下你的解釋然后對(duì)照三個(gè)標(biāo)準(zhǔn)檢查有沒(méi)有說(shuō)清 ThreadLocalMap 的 key 是弱引用、value 是強(qiáng)引用有沒(méi)有說(shuō)清為什么 key 弱引用還會(huì)泄漏有沒(méi)有說(shuō)清remove()在什么時(shí)機(jī)調(diào)用。任何一條卡住就回去補(bǔ)補(bǔ)完再講一遍。我一般會(huì)把這種講解錄成三分鐘的語(yǔ)音回聽(tīng)時(shí)專(zhuān)挑自己含糊的地方。含糊往往出現(xiàn)在兩個(gè)位置一是版本差異比如 JDK 8 和 JDK 17 在 GC 或集合實(shí)現(xiàn)上的變化二是邊界條件比如“大多數(shù)情況”和“一定”的區(qū)別。面試官追問(wèn)的往往就是這兩處。下面這張表是我用來(lái)檢查講解質(zhì)量的清單每道題過(guò)一遍比刷十遍 PDF 有用。檢查項(xiàng)合格標(biāo)準(zhǔn)常見(jiàn)不合格表現(xiàn)因果鏈能說(shuō)出至少三層為什么只答結(jié)論追問(wèn)就重復(fù)結(jié)論版本邊界能指出 JDK 版本差異把 JDK 8 的行為當(dāng)成所有版本反例能舉出一個(gè)失效場(chǎng)景只說(shuō)“一般”“通常”參數(shù)能說(shuō)出關(guān)鍵參數(shù)和默認(rèn)值參數(shù)名記混或默認(rèn)值說(shuō)錯(cuò)手寫(xiě)能默寫(xiě)出核心代碼結(jié)構(gòu)只記得 API 名字寫(xiě)不出邏輯這個(gè)清單不是讓你逐條背而是講解時(shí)自然覆蓋。我自己的血淚經(jīng)驗(yàn)是早期準(zhǔn)備時(shí)把 PDF 刷了三遍結(jié)果面試被問(wèn)“ConcurrentHashMap 的 size() 怎么實(shí)現(xiàn)的”直接卡住因?yàn)?PDF 只寫(xiě)了“線(xiàn)程安全”沒(méi)寫(xiě) size 的實(shí)現(xiàn)細(xì)節(jié)。后來(lái)我改用講解法每道題都逼自己講到能回答“怎么實(shí)現(xiàn)的”這一層才真正穩(wěn)下來(lái)。還有一點(diǎn)別等到面試前一周才開(kāi)始講平時(shí)每學(xué)一個(gè)模塊就講一次講完記下卡殼點(diǎn)那些就是你的復(fù)習(xí)重點(diǎn)。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取