證考試核心考點(diǎn)與易錯(cuò)點(diǎn)復(fù)習(xí)指南)
簡(jiǎn)介這份 PDF 面向備戰(zhàn) Oracle Java SE 17 開發(fā)者認(rèn)證Exam 1Z0-829的考生由 Jeanne Boyarsky 與 Scott Selikoff 編寫把考試大綱中的知識(shí)點(diǎn)轉(zhuǎn)化為可直接演練的模擬測(cè)試題適合已有一定 Java 基礎(chǔ)、希望在上考場(chǎng)前檢驗(yàn)薄弱環(huán)節(jié)的中高級(jí)開發(fā)者。壓縮包內(nèi)為 1 個(gè) PDF 文件約 20.96MB由 Wiley 出版發(fā)行內(nèi)容圍繞官方考試范圍編排覆蓋語言基礎(chǔ)、面向?qū)ο笤O(shè)計(jì)與實(shí)現(xiàn)、異常處理、集合與泛型、Stream 與 Lambda、模塊化系統(tǒng)、并發(fā)編程、I/O 與 JDBC 等模塊題目后附有解析與實(shí)用的復(fù)習(xí)策略便于理解考點(diǎn)原理而不只是死記答案。讀者可借助成套練習(xí)模擬真實(shí)考試節(jié)奏用錯(cuò)題反查知識(shí)盲區(qū)據(jù)此安排沖刺階段的復(fù)習(xí)順序解析側(cè)重考點(diǎn)辨析也方便培訓(xùn)講師挑選課后練習(xí)。目前已有 268 人學(xué)習(xí)下載適合考前自測(cè)、查漏補(bǔ)缺與二輪強(qiáng)化。1. 一張地圖Java SE 17 認(rèn)證考試到底在考什么先說一個(gè)反直覺的結(jié)論這門 Java SE 17 認(rèn)證考試不考你寫不寫得出業(yè)務(wù)代碼考的是你能不能在兩分鐘內(nèi)判斷一段代碼是「編譯不過」「運(yùn)行才炸」還是「看著別扭其實(shí)完全合法」。正因?yàn)槿绱耸忻嫔夏翘?1Z0-829 的實(shí)戰(zhàn)練習(xí)和模擬測(cè)試題才會(huì)顯得刁鉆題面短、選項(xiàng)近、錯(cuò)誤藏在一行注釋后面。很多人做完整套題才發(fā)現(xiàn)自己真正丟分的地方不是不會(huì)寫類而是漏看了訪問修飾符、看錯(cuò)了格式化模式字母的大小寫。把這十塊考綱攤開再疊起來其實(shí)只有四層語言地基日期時(shí)間、文本、數(shù)值、控制流、對(duì)象模型繼承、接口、記錄類、密封類、異常與斷言、數(shù)據(jù)結(jié)構(gòu)與流水線集合、泛型、Stream、并發(fā)、工程域I/O、模塊化、本地化。前兩層決定你能不能讀懂題后兩層決定你能不能排掉干擾項(xiàng)。適合已經(jīng)能寫 Java、想用一套系統(tǒng)復(fù)習(xí)策略把知識(shí)點(diǎn)串成地圖的人。2. 語言地基日期時(shí)間、文本、數(shù)值與控制流的復(fù)習(xí)重點(diǎn)2.1 日期時(shí)間不可變對(duì)象與 Period、Duration 的分工java.time這一族的題八成的失分不在 API 記不住而在忘了它們?nèi)遣豢勺儗?duì)象。LocalDate.plusDays(1)返回的是新實(shí)例原對(duì)象紋絲不動(dòng)代碼里寫date.plusDays(1);而不接返回值編譯能過、運(yùn)行不報(bào)錯(cuò)、結(jié)果就是沒變——這種題專治「我以為它在原地改」。類型表示什么常用場(chǎng)景LocalDate/LocalTime/LocalDateTime不帶時(shí)區(qū)的日期、時(shí)間、日期時(shí)間大多數(shù)本地計(jì)算ZonedDateTime帶時(shí)區(qū)規(guī)則的完整時(shí)間跨時(shí)區(qū)、夏令時(shí)Instant時(shí)間線上的一個(gè)點(diǎn)UTC 紀(jì)元秒時(shí)間戳、機(jī)器時(shí)間Period年、月、日只能作用于日期類Duration時(shí)、分、秒、納秒作用于時(shí)間、Instant最容易混的是Period和Duration的作用范圍給LocalDate加Duration編譯就不過給LocalTime加Period也一樣。Duration.ofHours(30).toHours()是 30但toMinutes()得到的是 1800toMinutesPart()才是 0截?cái)嗪腿∮嗟膮^(qū)別在題里經(jīng)常只差一個(gè)詞。// 注意大小寫MM 是月mm 是分HH 是 24 小時(shí)制hh 是 12 小時(shí)制dd 是日DD 是一年中的第幾天 DateTimeFormatter fmt DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); LocalDateTime dt LocalDateTime.of(2023, 3, 1, 9, 5, 0); System.out.println(fmt.format(dt)); // 2023-03-01 09:05:00 System.out.println(dt.plusDays(1).format(fmt)); // 原對(duì)象不變plusDays 返回新實(shí)例 // 解析失敗拋 DateTimeParseException它是 RuntimeException 的子類catch 寫成 IOException 會(huì)編譯不過 LocalDate parsed LocalDate.parse(2023-03-01, DateTimeFormatter.ISO_LOCAL_DATE);yyyy和YYYY不是同一個(gè)東西前者是紀(jì)元年后者是「基于周的年份」跨年那一周用YYYY會(huì)得到下一年的數(shù)字。同理MM和mm、HH和hh、ss和SSS這類字母大小寫在考察里幾乎是必出寫代碼時(shí)隨手用 IDE 的格式化提示反而察覺不到。2.2 文本塊與 String 新 API規(guī)則比方法更需要記文本塊有三條硬規(guī)則開頭的后面必須換行否則編譯不過內(nèi)容里的雙引號(hào)不需要轉(zhuǎn)義但連續(xù)三個(gè)引號(hào)要轉(zhuǎn)義收尾定界符的位置決定公共縮進(jìn)被裁掉多少。第三條是重災(zāi)區(qū)——把結(jié)束的頂格寫縮進(jìn)就全保留和最后一行內(nèi)容對(duì)齊縮進(jìn)就被裁掉。String sql SELECT id, name FROM demo_table WHERE id %d .formatted(7); // 反斜杠放在行尾表示「這一行不換行」\s 表示一個(gè)不會(huì)被裁掉的行尾空格 String joined a\ b; System.out.println(joined); // ab方法層面strip()和trim()的差別在于前者認(rèn) Unicode 空白后者只處理 ASCII 碼小于等于 32 的字符indent(int)傳正數(shù)是加空格傳負(fù)數(shù)只負(fù)責(zé)移除空白而不補(bǔ)齊isBlank()判的是「是否只有空白」空串返回 true。String.repeat(0)返回空串而不是異常lines()返回的是StreamString這些細(xì)節(jié)單獨(dú)看都很小湊在四個(gè)選項(xiàng)里就能篩掉一半人。2.3 數(shù)值、包裝類與類型提升的玄學(xué)都在這包裝類的緩存機(jī)制是經(jīng)典翻車點(diǎn)Integer在 -128 到 127 之間復(fù)用同一批對(duì)象用比較得到 true超出范圍就是 false。Long、Short、Character有類似機(jī)制Float和Double則根本沒有緩存兩個(gè)Double.valueOf(1.0)用永遠(yuǎn)是 false。Integer a 127, b 127; System.out.println(a b); // true包裝類緩存 -128~127 Integer c 128, d 128; System.out.println(c d); // false超出緩存范圍 // BigDecimal 的 equals 連精度一起比compareTo 只比數(shù)值 System.out.println(new BigDecimal(1.0).equals(new BigDecimal(1.00))); // false System.out.println(new BigDecimal(1.0).compareTo(new BigDecimal(1.00))); // 0字面量里的下劃線只能放在數(shù)字之間1_000合法_1000、1000_、1._0、0x_1全都不合法。三元運(yùn)算符的類型提升也常考boolean ? 1 : 2L的結(jié)果類型是long把int和double混在一起會(huì)提升成double而兩邊是包裝類時(shí)又要考慮拆箱true ? Integer.valueOf(1) : 1這種寫法在題里出現(xiàn)就得先想清楚會(huì)不會(huì) NPE。2.4 控制流switch 表達(dá)式與標(biāo)簽跳轉(zhuǎn)switch能接受的類型有限byte、short、char、int、對(duì)應(yīng)的包裝類、String、枚舉。long、float、double、boolean一律不允許case標(biāo)簽必須是編譯期常量。Java 17 的箭頭形式不會(huì)穿透一段代碼塊要返回值時(shí)必須顯式寫yield作為表達(dá)式的switch還要求窮盡枚舉少寫一個(gè)常量又沒default就是編譯錯(cuò)誤。// switch 表達(dá)式必須窮盡箭頭形式不穿透代碼塊里用 yield 交出值 String size switch (code) { case 1, 2 - small; case 3 - { String r medium; yield r; } default - unknown; };instanceof的模式匹配變量作用域要看清if (!(o instanceof String s)) return;之后的s是有效的但把條件寫成與||混合時(shí)變量的可用范圍會(huì)跟著短路邏輯走。標(biāo)簽跳轉(zhuǎn)outer:只能貼在最外層循環(huán)前break outer跳出整個(gè)循環(huán)continue outer只結(jié)束當(dāng)前這輪。至于不可達(dá)代碼while (false) { }后面的語句是編譯錯(cuò)誤而if (false) { }后面的語句合法——同樣是常量條件一個(gè)報(bào)錯(cuò)一個(gè)不報(bào)憑直覺猜很容易錯(cuò)。3. 對(duì)象模型繼承、接口、記錄類、密封類與異常的判定題3.1 訪問修飾符與重寫規(guī)則訪問控制是這類題的第一道篩子四個(gè)修飾符的范圍必須閉著眼都能畫出來。修飾符同一個(gè)類同一個(gè)包子類任意位置private可見不可見不可見不可見默認(rèn)無修飾符可見可見不可見不可見protected可見可見可見不可見public可見可見可見可見重寫要同時(shí)滿足四條方法簽名一致、返回類型協(xié)變或相同、不能降低可見性、不能拋出更寬的受檢異常。static方法不能被重寫子類寫同名同參只是隱藏private方法同理子類里寫一個(gè)「看起來像重寫」的方法完全合法只是不構(gòu)成多態(tài)。變量則根本沒有重寫這回事父類引用指向子類對(duì)象時(shí)取到的是父類那份字段值。class Parent { static { System.out.print(1); } // 父類靜態(tài)塊類初始化時(shí)執(zhí)行且只一次 { System.out.print(2); } // 父類實(shí)例塊按聲明順序 Parent() { System.out.print(3); } // 父類構(gòu)造器體 } class Child extends Parent { static { System.out.print(4); } { System.out.print(5); } Child() { System.out.print(6); } } new Child(); // 輸出 142356這個(gè)順序值得背下來父類靜態(tài)塊 → 子類靜態(tài)塊 → 父類實(shí)例塊與字段 → 父類構(gòu)造器 → 子類實(shí)例塊與字段 → 子類構(gòu)造器。this()和super()不能同時(shí)出現(xiàn)而且必須是構(gòu)造器的第一條語句所以題里那種「先打印一行再調(diào)super()」的寫法必然是編譯錯(cuò)誤。3.2 接口、記錄類與密封類接口的三類方法要分清default方法可被繼承也可被重寫static方法屬于接口本身、不被繼承私有方法只能給接口內(nèi)部的default方法調(diào)用。兩個(gè)接口給出同簽名的default方法時(shí)實(shí)現(xiàn)類必須重寫否則編譯不過——這條幾乎是必考。接口里的字段隱式為public static final寫int X 1;之后想再賦值就是編譯錯(cuò)誤。記錄類是 Java 17 的高頻考點(diǎn)規(guī)則密集但都很好記隱式final不能聲明實(shí)例字段組件訪問器是x()而不是getX()可以帶靜態(tài)字段和靜態(tài)方法可以實(shí)現(xiàn)接口不能繼承別的類。緊湊構(gòu)造器不寫參數(shù)列表用來做校驗(yàn)如果要寫普通構(gòu)造器第一條語句必須委托給規(guī)范構(gòu)造器。record Point(int x, int y) { Point { // 緊湊構(gòu)造器不寫參數(shù)列表 if (x 0) throw new IllegalArgumentException(x 0); } Point(int v) { this(v, v); } // 其他構(gòu)造器必須委托給規(guī)范構(gòu)造器 }密封類看兩點(diǎn)permits列出的子類必須存在且每個(gè)子類必須標(biāo)注final、sealed或non-sealed三者之一如果都在同一個(gè)模塊里可以省掉permits讓編譯器從同一個(gè)文件里推斷。子類和父類不在同一個(gè)包未命名模塊時(shí)就編譯不過這條在選擇題里通常被包裝成「跨包繼承」的樣子。sealed interface Shape permits Circle, Square {} // 子類必須 final / sealed / non-sealed record Circle(double r) implements Shape {} final class Square implements Shape {}3.3 異常與斷言三層結(jié)構(gòu)與執(zhí)行順序異常體系先分三層Throwable之下是Error和ExceptionException之下再分RuntimeException非受檢和其他受檢異常。題里最愛考的是「哪些是受檢」NullPointerException、IllegalArgumentException、NumberFormatException、ClassCastException、ArithmeticException全是非受檢IOException、SQLException、InterruptedException是受檢。捕獲順序上子類異常必須寫在父類前面否則編譯錯(cuò)誤多重捕獲catch (A | B e)里的e隱式final不能再賦值。try-with-resources的兩個(gè)細(xì)節(jié)關(guān)閉順序與聲明順序相反如果try塊和close()都拋異常close()的異常會(huì)作為 suppressed 掛在主異常上用getSuppressed()取。資源變量隱式final在try塊里重新賦值是編譯錯(cuò)誤。finally里寫return會(huì)覆蓋try里的返回值和異常這屬于「編譯器不攔、運(yùn)行結(jié)果反直覺」的典型。class R implements AutoCloseable { private final String name; R(String n) { name n; } public void close() { System.out.print(name); } } try (R a new R(A); R b new R(B)) { } // 輸出 BA關(guān)閉順序與聲明順序相反斷言要單獨(dú)記assert默認(rèn)關(guān)閉必須用-ea打開才生效失敗時(shí)拋的是AssertionError而不是異常assert x 0 : msg;里的冒號(hào)后面是消息表達(dá)式。重寫方法時(shí)拋出的受檢異常不能比父類版本更寬但可以更窄甚至不拋非受檢異常則不受這條限制。4. 數(shù)據(jù)結(jié)構(gòu)與流水線集合、泛型、Stream 與并發(fā)的題眼4.1 集合實(shí)現(xiàn)類的選擇與代價(jià)集合題的套路是先看「能不能存 null」再看「是不是有序」最后看「并發(fā)下會(huì)不會(huì)炸」。實(shí)現(xiàn)類允許 null 元素有序性典型考點(diǎn)ArrayList允許插入順序隨機(jī)訪問快中間刪除慢LinkedList允許插入順序同時(shí)實(shí)現(xiàn)List與DequeArrayDeque不允許插入順序作棧或隊(duì)列用push(null)拋 NPEHashSet/HashMap允許HashMap允許一個(gè) null 鍵無序依賴hashCode與equalsTreeSet/TreeMap不允許排序元素必須可比較否則ClassCastExceptionConcurrentHashMap不允許無序鍵值都不能為 nullList.of()、Set.of()、Map.of()返回的都是不可變集合傳 null 直接 NPESet.of()里放重復(fù)元素拋IllegalArgumentException。Arrays.asList()是固定長(zhǎng)度而非不可變add和remove拋UnsupportedOperationException但set可以改。遍歷時(shí)刪除元素要用Iterator.remove()或removeIf直接list.remove()會(huì)得到ConcurrentModificationException。4.2 泛型與比較器PECS 別背反泛型擦除決定了new ArrayListString().getClass() new ArrayListInteger().getClass()為 true也決定了不能寫new T[]、不能寫new ListString[10]。通配符的方向按 PECS 記List? extends Number是生產(chǎn)者只能讀不能寫List? super Integer是消費(fèi)者能寫但讀出來只能是Object。題里常把這兩個(gè)寫反讓你判斷哪一行編譯不過。比較器則有兩條主線Comparable是「自己和自己比」compareTo返回 0 表示相等Comparator是外部比較器可以鏈?zhǔn)浇M合。Comparator.comparing(Person::name).thenComparingInt(Person::age)是先按名字再按年齡.reversed()只反轉(zhuǎn)緊挨著的那一段寫在整個(gè)鏈子末尾和寫在中間結(jié)果完全不同。用TreeSet裝沒實(shí)現(xiàn)Comparable又沒給Comparator的對(duì)象第一次add就拋ClassCastException而不是在編譯期報(bào)錯(cuò)。4.3 Stream 管道的惰性與終止操作Stream 題的核心只有一句話中間操作是惰性的終止操作才觸發(fā)執(zhí)行而且一條流只能消費(fèi)一次。map是一對(duì)一flatMap是一對(duì)多再攤平peek是中間操作只該用來觀察count()這類終止操作在元素個(gè)數(shù)已知時(shí)可能壓根不遍歷peek一行都不打印。ListString names List.of(Amy, Bob, Ada); MapInteger, ListString byLen names.stream() .collect(Collectors.groupingBy(String::length)); // 長(zhǎng)度 - 名字列表 // peek 是中間操作只用于觀察流水線不能當(dāng) forEach 用 long n names.stream().peek(System.out::println).count();Collectors.toMap遇到重復(fù)鍵拋IllegalStateException需要傳合并函數(shù)才不炸partitioningBy返回的 Map 一定有兩個(gè)鍵true和falsefindFirst在并行流里仍保證取第一個(gè)findAny則不保證。Optional的orElse無論是否為空都會(huì)求值orElseGet才惰性這一條在帶副作用的例子里經(jīng)常被拿來出題。4.4 并發(fā)的四個(gè)必考點(diǎn)并發(fā)部分先分清Runnable和Callable前者run()無返回值不能拋受檢異常后者call()有返回值可以拋。ExecutorService.execute提交任務(wù)無返回submit返回Futureget()阻塞并可能拋ExecutionException、InterruptedException、TimeoutException。shutdown()只是不再接新任務(wù)、不阻塞awaitTermination才阻塞等待忘記關(guān)閉線程池JVM 就不退出。線程狀態(tài)六個(gè)值、synchronized與wait/notify必須在同步塊內(nèi)調(diào)用、AtomicInteger保證單變量原子性、CountDownLatch一次性而CyclicBarrier可重用這幾條屬于「記了就能拿分」。并行流用的是公共 ForkJoin 池lambda 里改共享的可變狀態(tài)結(jié)果順序和數(shù)值都不確定要保證順序得用forEachOrdered。5. 易錯(cuò)點(diǎn)五個(gè)反復(fù)翻車的判定盲區(qū)5.1 格式化與本地化模式字母和資源文件命名易漏點(diǎn)yyyy與YYYY、MM與mm、HH與hh混用以及ResourceBundle的基名拼寫。資源文件的查找順序是「基名_語言_國家 → 基名_語言 → 基名 → 默認(rèn) locale 的對(duì)應(yīng)文件」少一級(jí)就落到別的文件上程序不報(bào)錯(cuò)只是取到了錯(cuò)誤的文案。為什么漏這些字符串長(zhǎng)得太像寫代碼時(shí) IDE 不校驗(yàn)?zāi)J阶帜钢挥性谶\(yùn)行時(shí)才發(fā)現(xiàn)輸出多了或少了幾個(gè)小時(shí)資源文件的命名錯(cuò)誤也不會(huì)拋異?;赝藱C(jī)制把它悄悄兜住了。怎么補(bǔ)把模式字母抄成一張對(duì)照表貼在錯(cuò)題本第一頁本地化部分固定用ResourceBundle.getBundle(messages, locale)加三個(gè)層級(jí)的屬性文件做一次實(shí)測(cè)看清楚每一級(jí)命中的是哪個(gè)文件再回頭做模擬測(cè)試?yán)锏耐愵}。5.2 泛型通配符與重載解析易漏點(diǎn)List? extends T里add編譯不過List? super T里get只能拿到Object兩個(gè)重載方法一個(gè)收List?、一個(gè)收ListString調(diào)用時(shí)選哪個(gè)。為什么漏方向背反了也能跑通大部分日常代碼因?yàn)槠綍r(shí)寫的都是具體類型重載解析則牽涉泛型擦除ListString和ListInteger擦除后是同一個(gè)類型編譯器會(huì)挑「最具體」的那個(gè)。怎么補(bǔ)準(zhǔn)備一段五行以內(nèi)的小程序把上界、下界、無界三種寫法的讀寫操作各試一遍看編譯器在哪一行報(bào)錯(cuò)重載那類題不要靠推理直接在 jshell 里敲一遍記住了報(bào)錯(cuò)信息比記住結(jié)論更管用。5.3 資源關(guān)閉順序與 finally 的覆蓋易漏點(diǎn)try-with-resources的關(guān)閉順序是聲明的逆序close()拋出的異常會(huì)成為 suppressedfinally里的return會(huì)吞掉try中的異常。為什么漏正常路徑下順序無關(guān)緊要只有異常路徑才暴露差異而練習(xí)題恰恰專挑異常路徑finally的覆蓋行為編譯器完全不提示。怎么補(bǔ)寫一個(gè)實(shí)現(xiàn)AutoCloseable的小類聲明兩個(gè)實(shí)例并在try塊里拋異常把getSuppressed()的內(nèi)容打印出來凡是看到finally里帶return或賦值語句的題直接判定為反例。5.4 模塊路徑與類路徑的混用易漏點(diǎn)module-info.java里的requires、exports、opens語義搞混把模塊化的 jar 丟到類路徑上模塊描述符被忽略。為什么漏模塊系統(tǒng)在實(shí)際項(xiàng)目里用得少光是「能編譯能運(yùn)行」就不容易觸發(fā)邊界exports與opens的差別前者是編譯期可訪問后者是運(yùn)行期反射可訪問在單模塊場(chǎng)景里體現(xiàn)不出來。怎么補(bǔ)手動(dòng)建兩個(gè)模塊一個(gè)導(dǎo)出包、一個(gè)requires它先跑通再把exports改成opens觀察編譯期和反射訪問分別在何時(shí)失敗。比起背定義失敗一次記得牢。5.5 并行流與線程池的狀態(tài)泄漏易漏點(diǎn)并行流里修改共享集合線程池創(chuàng)建后不shutdown程序跑完不退出submit返回的Future不get異常被靜默吞掉。為什么漏小數(shù)據(jù)量下并行流往往按順序執(zhí)行看不出問題異常藏在Future里不在主線程棧上控制臺(tái)一片安靜。怎么補(bǔ)寫一個(gè)IntStream.range(0, 10_000).parallel()往ArrayList里add的 Demo跑幾次看看結(jié)果長(zhǎng)度是否穩(wěn)定線程池的練習(xí)一律加try/finally包住shutdown()和awaitTermination把這條當(dāng)成肌肉記憶。6. 復(fù)習(xí)清單把十個(gè)考點(diǎn)域壓成一張自測(cè)表復(fù)習(xí)到中后段最怕的是「每塊都看過、每塊都不敢說會(huì)」。我自己的做法是把十個(gè)考點(diǎn)域壓成一張表每行只填三件事這一域的必背結(jié)論、最容易錯(cuò)的那一條、用什么方式自測(cè)。表格填不滿的地方就是下一輪該重點(diǎn)補(bǔ)的地方??键c(diǎn)域必背結(jié)論自測(cè)方式日期時(shí)間全部不可變Period歸日期、Duration歸時(shí)間手寫三種格式化模式并預(yù)測(cè)輸出文本與數(shù)值文本塊三條規(guī)則、包裝類緩存區(qū)間改一行代碼看是否編譯過控制流switch支持的類型與窮盡性把if/else改寫成switch表達(dá)式面向?qū)ο笾貙懰臈l件、初始化順序數(shù)一遍打印順序再運(yùn)行記錄類與密封類緊湊構(gòu)造器、子類三選一故意漏寫final看報(bào)錯(cuò)異常與斷言受檢非受檢分類、關(guān)閉逆序造 suppressed 異常打印鏈集合null 支持與有序性對(duì)照表換實(shí)現(xiàn)類跑同一段代碼泛型與比較器PECS 方向、thenComparing順序?qū)懮舷陆绺饕淮巫x寫Stream惰性、只能消費(fèi)一次、toMap沖突加peek看是否被跳過并發(fā)與 I/O線程池關(guān)閉、Path與Files分工跑一遍-ea打開斷言自測(cè)環(huán)節(jié)有兩件事必須親自動(dòng)手別在腦子里推。第一件是斷言默認(rèn)關(guān)閉不打開就等于沒寫第二件是語法點(diǎn)猜錯(cuò)一次比看十遍定義有用。# 斷言默認(rèn)關(guān)閉必須顯式打開否則 assert 語句等于不存在 javac SelfCheck.java java -ea SelfCheck # 語法點(diǎn)直接在 jshell 里試比翻筆記快 jshell --class-path out做完一套模擬測(cè)試后的歸因也要固定流程錯(cuò)題只分三類——沒記住的結(jié)論、看漏的關(guān)鍵字、理解偏的語義。第一類補(bǔ)記憶卡第二類練審題把修飾符、返回值、異常類型用鉛筆圈出來第三類才值得回爐重看。前兩類占多數(shù)的時(shí)候繼續(xù)刷題收益最高第三類一多就該停下來把整章重新梳理一遍而不是硬刷下一套。從那以后我每次做完一套實(shí)戰(zhàn)練習(xí)都會(huì)強(qiáng)制走一遍這套歸因流程先把錯(cuò)題的錯(cuò)因?qū)懗梢粋€(gè)短句再對(duì)回表格里的某一行最后只復(fù)習(xí)那一行涉及的知識(shí)點(diǎn)絕不整章重看。堅(jiān)持幾套下來錯(cuò)題會(huì)明顯收斂到固定的兩三個(gè)域上那時(shí)候再集中補(bǔ)效率比平均用力高得多。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取