公司动态

Java零基础暑期学习路线:从环境搭建到集合与异步编程全攻略

📅 2026/8/30 18:07:39
Java零基础暑期学习路线:从环境搭建到集合与异步编程全攻略
暑假是一年中最适合系统性学习 Java 的时间段。没有学校课程打断也没有实习和秋招的压力可以连续投入一到两个月把基础打牢。但很多零基础的同学打开 B 站搜索 Java 教程时反而会陷入选择困难视频太多了这个讲变量那个讲集合还有一堆xx天精通 Java的标题完全不知道从哪个系列开始看。更常见的问题是视频看懂了代码一写就报错报错信息看不懂只能百度但百度出来的答案又是零散的很多还针对不同版本试了半天也没解决。学了一个暑假感觉什么都听过又什么都写不出来。这篇文章的目的就是帮你把这条混乱的学习路径梳理清楚。我会围绕 Java 零基础入门的完整学习路线把每个阶段的知识点、可复制运行的代码示例、高频报错的排查思路、以及面试常见的考点整理成一份系统化的学习笔记。内容覆盖 JDK 环境搭建、基础语法、面向对象、集合框架、排序算法、Lambda 与 CompletableFuture 异步编程基本就是零基础阶段需要掌握的全部主线内容。你不需要把本文一次性读完建议对照自己的学习进度学到哪一节就翻到哪一节配合代码动手练习。1. 先搞清楚零基础学 Java 到底在学什么很多初学者把 Java 学习理解成记住语法于是买了一本语法书从第 1 页啃到第 500 页结果越啃越迷糊。实际上Java 作为一门面向对象语言它的知识体系可以拆成三个层次。第一层是语言基础包括变量、数据类型、运算符、流程控制、数组、方法这些内容。这一层解决的是怎么写代码的问题也是所有编程语言的通用部分。第二层是面向对象思想包括类与对象、封装、继承、多态、接口、枚举。这一层是 Java 的核心也是它区别于 C 语言这类面向过程语言的关键。面试中的高频考点如重载和重写的区别抽象类和接口的区别都来自这一层。第三层是生态与工具包括集合框架、泛型、异常处理、Lambda、流式编程、并发编程以及 Maven、Git、IDE 这些工程化工具。这一层决定了你能不能真正参与项目开发。所以零基础阶段的学习目标不是看完一套教程而是三个可检验的能力能独立分析一个简单问题并写出完整可运行的 Java 程序能读懂编译报错和运行时报错根据异常信息定位问题能说出常用集合、字符串、异常处理等 API 的适用场景。1.1 Java 为什么值得零基础入门很多初学者会纠结现在学 Python 是不是更好学 Go 是不是更有前途其实语言本身没有绝对的好坏关键看你的目标是什么。Java 的优势主要体现在三个方面。第一就业面广。后端开发、Android 开发、大数据生态Hadoop、Spark、Flink 底层都是 JVM 体系、中间件开发都需要 Java 技术栈。哪怕你将来不打算做纯后端Java 的基础知识也是很多大厂笔试和面试的必考内容。第二语法严谨适合打基础。Java 强制要求类型声明、访问修饰符、异常处理这种约束感对新手反而是好事。它逼着你在一开始就养成规范的编码习惯以后再学其他语言会轻松很多。第三资料和社区非常成熟。无论是学习路线、面试题还是各种踩坑记录Java 生态的资料是所有编程语言里最完备的。遇到报错基本上都能搜到解决方案这对零基础自学者非常重要。1.2 两个月时间应该掌握到什么程度如果从 7 月初开始到 8 月底结束按每天有效学习 3 到 4 小时来计算完整走完一套基础路线是完全够用的。学完你应该达到的状态能独立完成一个控制台版本的学生管理系统或图书管理系统能熟练使用集合、循环、方法、面向对象来解决实际逻辑问题能解释 HashMap 的底层结构、ArrayList 和 LinkedList 的区别这类基础面试题能看懂编译报错和运行异常并独立完成大部分常见问题的排查。达不到这个状态往往不是因为智商而是因为看视频时间和写代码时间的比例严重失衡。看视频是输入写代码才是输出输出才能暴露问题。2. 2026 暑假版 Java 学习路线总览下面这条路线是我比较推荐给零基础同学的两月制学习路线。它把内容分为五个阶段每个阶段都有明确的学习目标和验证方式。阶段时间安排核心内容阶段验证第一阶段第 1-2 周JDK 安装、IDE 使用、基础语法、流程控制、数组完成 10 道编程练习题第二阶段第 3-4 周面向对象、异常处理、常用类、枚举完成一个学生管理系统的类设计第三阶段第 5 周集合框架、泛型、排序算法用集合重写学生管理系统第四阶段第 6-7 周Lambda、Stream、IO、CompletableFuture实现一个文件批量处理小工具第五阶段第 8 周面试题复习、项目复盘、查漏补缺能口述高频面试题2.1 每天的学习时间怎么分配我建议每天的学习分成三块第一块看视频学习新知识控制在 1.5 到 2 小时以内不要连续看超过 2 小时第二块动手写代码至少 1.5 小时把视频里的示例自己敲一遍再独立完成课后练习第三块整理笔记20 到 30 分钟记录当天学到的知识点、易错点和报错信息。注意这里有一个很关键的原则先敲代码再整理笔记。很多同学喜欢一边看视频一边截图结果截图存了几百张代码一行都没写过。笔记和截图只有在代码实践之后整理才有价值。2.2 关于收藏了等于学会了几乎每个自学教程下面都会有人说先收藏以后再看。但根据我的经验Java 零基础阶段最忌讳的就是把学习资料当成收藏品。处理方式很简单收藏夹里的内容一周之内如果还没打开看就直接删掉。这会强迫自己在第一时间消化内容而不是无限期拖延。3. 环境准备JDK 安装与环境变量配置Java 程序要运行必须先安装 JDKJava Development KitJava 开发工具包。环境搭建是最容易劝退新手的环节很多同学的第一道坎不是语法而是环境变量配置失败。这一节把步骤和原理都说清楚。3.1 JDK 版本怎么选目前市面上常见的 JDK 版本有 JDK 8、JDK 11、JDK 17 等。很多老项目还在用 JDK 8而 Spring Boot 3 框架已经要求 JDK 17 起步。对零基础新手我的建议是直接使用 JDK 17。原因有三个JDK 17 是长期支持版本稳定性有保障它包含了 switch 表达式、文本块、记录类等现代语法让代码更简洁目前主流框架和招聘需求都在向 JDK 17 迁移学习它更贴合当前技术趋势。如果你后面进入公司发现项目还在用 JDK 8那也不用慌。JDK 8 的基础语法和 JDK 17 差别不大核心的 Java SE 语法是通用的切换成本很低。3.2 Windows 环境变量配置步骤以 Windows 系统为例安装好 JDK 之后需要配置两个环境变量。第一步新建JAVA_HOME变量指向 JDK 安装目录。JAVA_HOMEC:\Program Files\Java\jdk-17第二步找到Path变量在原有值后面新增一行%JAVA_HOME%\bin这里的原理是JAVA_HOME用来给其他依赖 JDK 的软件比如 Maven、Tomcat、IDEA提供 JDK 路径而Path的作用是让系统能在任何目录下直接识别java和javac命令。因为javac.exe和java.exe就在JAVA_HOME\bin目录里。配置完成后重新打开一个命令行窗口输入以下命令验证java -version javac -version如果能看到类似下面的输出说明环境配置成功java version 17.0.10 2024-01-16 LTS Java(TM) SE Runtime Environment (build 17.0.107) Java HotSpot(TM) 64-Bit Server VM (build 17.0.107, mixed mode, sharing)如果你的系统是 macOS 或 Linux配置方式类似只是环境变量文件不同。macOS 通常在~/.zshrc中配置Linux 通常在~/.bashrc中配置export JAVA_HOME/usr/lib/jvm/java-17-openjdk-amd64 export PATH$JAVA_HOME/bin:$PATH配置完后执行source ~/.zshrc或source ~/.bashrc使其生效。3.3 环境变量常见的配置问题新手最常遇到的问题是命令行提示java 不是内部或外部命令。原因通常是 Path 配置错误或者配置完成后没有重新打开命令行窗口。检查顺序是先确认JAVA_HOME路径下真的存在bin目录再确认Path里有没有写错变量名。还有一个容易被忽略的点如果系统里同时安装了多个 JDKPath中排在前面的 JDK 会生效。排查版本混乱问题时可以用where javaWindows或which javaLinux/macOS查看实际调用的路径。4. Java 基础语法核心环境搭好之后就可以进入语法学习阶段。这一部分内容多但难度不大关键是每个知识点都要配代码练习。下面挑几个容易出错、面试也常考的点展开。4.1 标识符命名规则Java 中的标识符就是变量名、方法名、类名的统称。它的规则必须记牢因为这些是编译期的硬性规定。规则如下只能由字母、数字、下划线_和美元符号$组成不能以数字开头不能是 Java 关键字比如class、public、static、void严格区分大小写age和Age是两个不同的变量名。int age 18; // 合法 int age2 20; // 合法 String userName 张三; // 合法驼峰命名 // int 2age 18; // 编译错误不能以数字开头 // int class 1; // 编译错误class 是关键字除了硬性规则还有一条约定俗成的规范类名使用大驼峰命名StudentInfo变量名和方法名使用小驼峰命名studentName、getStudentName常量使用全大写加下划线MAX_COUNT。4.2 运算符与表达式运算符是程序的基本组成单元。Java 的运算符分为算术运算符、赋值运算符、关系运算符、逻辑运算符、三元运算符和位运算符。零基础阶段重点掌握前五种即可。int a 10; int b 3; System.out.println(a b); // 13 System.out.println(a - b); // 7 System.out.println(a * b); // 30 System.out.println(a / b); // 3注意整数相除结果还是整数 System.out.println(a % b); // 1取余运算 // 关系运算结果是布尔值 System.out.println(a b); // true System.out.println(a b); // false // 逻辑运算 boolean flag (a b) (b 0); System.out.println(flag); // true // 三元运算符 int max a b ? a : b; System.out.println(max); // 10这里最容易出错的是整数除法。10 / 3的结果是3而不是3.33因为两个 int 相除结果还是 int。如果需要得到小数至少要把其中一个操作数转为 double比如10.0 / 3。4.3 流程控制与数组流程控制包括if-else、switch、for、while、do-while这些是写逻辑的基础。// for 循环遍历数组 String[] languages {Java, Python, Go, C}; for (int i 0; i languages.length; i) { System.out.println(第 i 个语言是 languages[i]); } // 增强 for 循环 for (String lang : languages) { System.out.println(lang); } // while 循环累加 int sum 0; int i 1; while (i 100) { sum i; i; } System.out.println(1加到100的结果是 sum); // 5050数组是一个很基础但很重要的数据结构。数组的长度用length属性获取下标从 0 开始。这个概念虽然简单但很多运行时报错都和它有关。4.4 数组越界异常数组越界是零基础学员遇到最多的运行时报错之一。看下面这个例子int[] arr {1, 2, 3}; System.out.println(arr[3]); // 运行时抛出异常运行结果Exception in thread main java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3这段报错信息其实已经把问题说得很清楚了Index 3表示访问的下标是 3out of bounds for length 3表示数组长度是 3。长度为 3 的数组有效下标只有 0、1、2访问下标 3 自然越界。排查思路很简单先看异常信息里的Index和length再检查循环边界。如果你写的是i arr.length那最后一次循环一定会越界正确写法是i arr.length。5. 面向对象编程从类到设计思想面向对象是 Java 的核心也是从会写代码到会设计代码的转折点。很多同学在这一阶段掉队是因为不理解为什么要这么设计。下面从实际场景出发来讲解。5.1 类与对象类是对一类事物的抽象对象是类的具体实例。以学生为例学生有名字和年龄这些属性有学习这个行为。用 Java 来描述就是这样// 文件路径src/main/java/com/example/entity/Student.java public class Student { private String name; private int age; public Student(String name, int age) { this.name name; this.age age; } public void study() { System.out.println(name 正在学习 Java); } public String getName() { return name; } public void setName(String name) { this.name name; } }使用这个类// 文件路径src/main/java/com/example/Main.java public class Main { public static void main(String[] args) { Student stu new Student(小明, 20); stu.study(); // 小明 正在学习 Java } }这里有几个关键点需要理解private关键字把字段设为私有外部不能直接访问只能通过getName、setName这些公共方法访问。这就是封装。this关键字用来区分成员变量和局部变量。构造方法里的this.name name左边是对象的成员变量右边是传入的参数。构造方法用于创建对象时初始化属性。5.2 封装、继承、多态面向对象的三大特性是封装、继承、多态这三者经常在面试题里一起出现。封装的核心是隐藏内部实现对外暴露稳定的接口。最典型的体现就是private字段加getter/setter方法。继承用extends关键字实现子类可以复用父类的属性和方法。多态是指同一个方法在不同对象上有不同的表现。看下面这个经典例子// 文件路径src/main/java/com/example/oop/Animal.java class Animal { protected String name; public Animal(String name) { this.name name; } public void speak() { System.out.println(name 发出声音); } } // 文件路径src/main/java/com/example/oop/Dog.java class Dog extends Animal { public Dog(String name) { super(name); } Override public void speak() { System.out.println(name 汪汪叫); } } // 文件路径src/main/java/com/example/oop/Cat.java class Cat extends Animal { public Cat(String name) { super(name); } Override public void speak() { System.out.println(name 喵喵叫); } } // 文件路径src/main/java/com/example/oop/TestAnimal.java public class TestAnimal { public static void main(String[] args) { Animal dog new Dog(旺财); Animal cat new Cat(咪咪); dog.speak(); // 旺财 汪汪叫 cat.speak(); // 咪咪 喵喵叫 } }关键点在于Animal dog new Dog(旺财)这一行。变量类型是Animal但实际对象是Dog。调用speak()方法时JVM 会走到实际对象的Dog.speak()而不是父类的speak()。这就是多态。5.3 枚举类型的使用枚举用于定义一组固定的常量。在业务代码里订单状态、用户角色、支付方式这些场景都适合用枚举。// 文件路径src/main/java/com/example/enums/OrderStatus.java public enum OrderStatus { PENDING(待支付), PAID(已支付), SHIPPED(已发货), DONE(已完成); private final String desc; OrderStatus(String desc) { this.desc desc; } public String getDesc() { return desc; } }使用方式OrderStatus status OrderStatus.PAID; System.out.println(status); // PAID System.out.println(status.getDesc()); // 已支付 // switch 配合枚举 switch (status) { case PENDING: System.out.println(去支付); break; case PAID: System.out.println(等待发货); break; default: System.out.println(订单已完成); }用枚举的好处是类型安全。如果用普通字符串或整数表示状态很容易拼错或写出无法理解的魔法数字。枚举把状态集中管理还允许给每个枚举值附加属性。6. 常用类与集合框架入门学完面向对象你已经能写出有结构的代码了。接下来要解决的是怎么管理一大堆数据的问题这就要用到集合框架。6.1 String 与包装类字符串是实际开发中使用最频繁的类。String 是不可变对象每次修改字符串都会生成新的对象。因此在循环中拼接字符串时不要使用而应该用 StringBuilder。字符串比较是新手最容易踩坑的地方。String s1 hello; String s2 hello; String s3 new String(hello); System.out.println(s1 s2); // true都在常量池中地址相同 System.out.println(s1 s3); // false一个在常量池一个在堆中 System.out.println(s1.equals(s3)); // true比较的是内容结论非常明确字符串比较内容时必须使用equals()方法不要使用。比较的是对象的引用地址只有两个字符串指向同一个对象时才返回 true。6.2 集合框架List、Set、Map集合框架是 Java 中的重中之重面试必考。零基础阶段需要重点掌握三个接口List有序、可重复常用实现类有 ArrayList 和 LinkedListSet无序、不可重复常用实现类有 HashSet、TreeSetMap键值对存储常用实现类有 HashMap、TreeMap。// List 示例 ListString list new ArrayList(); list.add(Java); list.add(Python); list.add(Java); System.out.println(List 大小: list.size()); // 3允许重复 // Set 示例 SetString set new HashSet(); set.add(Java); set.add(Python); set.add(Java); System.out.println(Set 大小: set.size()); // 2自动去重 // Map 示例 MapString, Integer map new HashMap(); map.put(Java, 1); map.put(Python, 2); System.out.println(map.get(Java)); // 1 System.out.println(map.containsKey(Go)); // false // 遍历 Map for (Map.EntryString, Integer entry : map.entrySet()) { System.out.println(entry.getKey() - entry.getValue()); }初学阶段不需要立刻深入 HashMap 的底层实现但要先知道它的基本特点HashMap 基于数组加链表JDK 8 之后是数组加链表加红黑树实现存取效率高但顺序不保证。这部分细节可以留到学完基础之后再看源码。6.3 一个简单的顺序表实现为了加深对集合的理解建议自己动手实现一个简化版的 ArrayList也就是顺序表。顺序表的本质是一个底层数组在添加元素时如果容量不够就扩容。// 文件路径src/main/java/com/example/collection/MyArrayList.java public class MyArrayList { private Object[] data; private int size; public MyArrayList() { data new Object[10]; size 0; } public void add(Object element) { if (size data.length) { grow(); } data[size] element; } private void grow() { Object[] newData new Object[data.length * 2]; System.arraycopy(data, 0, newData, 0, data.length); data newData; } public Object get(int index) { if (index 0 || index size) { throw new IndexOutOfBoundsException(下标越界: index); } return data[index]; } public int size() { return size; } }这个实现虽然简单但它包含了集合类的核心思想封装底层数组、动态扩容、边界校验。自己写一遍之后再去看 ArrayList 的源码就会轻松很多。7. 排序算法 Java 实现冒泡与快排排序算法是数据结构的基础也是面试中手写代码的高频题目。零基础阶段建议手写两个排序就够了冒泡排序和快速排序。7.1 冒泡排序冒泡排序的思路是重复遍历数组比较相邻两个元素顺序错误就交换。每一轮遍历后最大的元素会像气泡一样浮到最后。// 文件路径src/main/java/com/example/algorithm/SortUtil.java public class SortUtil { public static void bubbleSort(int[] arr) { int n arr.length; for (int i 0; i n - 1; i) { boolean swapped false; for (int j 0; j n - 1 - i; j) { if (arr[j] arr[j 1]) { int temp arr[j]; arr[j] arr[j 1]; arr[j 1] temp; swapped true; } } // 如果这一轮没有发生交换说明数组已经有序提前结束 if (!swapped) { break; } } } }冒泡排序的时间复杂度是 O(n²)空间复杂度是 O(1)。上面代码里加了一个swapped标记当数组本身有序时第一轮就能提前退出最优时间复杂度降为 O(n)。这个小优化在面试中很加分。7.2 快速排序快速排序使用分治思想选取一个基准值将数组分成左边小于基准、右边大于基准的两个部分然后递归排序。public static void quickSort(int[] arr, int left, int right) { if (left right) { return; } int pivot arr[left]; int i left; int j right; while (i j) { // 从右往左找第一个小于基准的值 while (i j arr[j] pivot) { j--; } arr[i] arr[j]; // 从左往右找第一个大于基准的值 while (i j arr[i] pivot) { i; } arr[j] arr[i]; } arr[i] pivot; // 递归排序左右两部分 quickSort(arr, left, i - 1); quickSort(arr, i 1, right); }调用方式int[] arr {5, 2, 9, 1, 7, 6}; SortUtil.quickSort(arr, 0, arr.length - 1); System.out.println(Arrays.toString(arr)); // [1, 2, 5, 6, 7, 9]快速排序的平均时间复杂度是 O(n log n)最坏情况是 O(n²)发生在每次基准值都选到最大值或最小值时。面试中如果能说出这一点说明你真的理解了它。7.3 怎么分析算法好坏衡量算法好坏最常用的指标是时间复杂度和空间复杂度。时间复杂度描述的是运行时间随数据规模增长的趋势通常使用大 O 表示法。初学阶段不用死记硬背先理解两个结论O(1) 表示常量时间和规模无关O(n) 表示线性增长数据量翻倍时间也约翻倍O(n²) 表示平方增长数据量稍微变大运行时间就急剧增加。在数据量小的时候冒泡排序和快速排序的差距看不出来但数据量到 10 万级别时差距就非常明显了。这也是为什么工程中几乎不使用冒泡排序的真实原因。8. 进阶必学Lambda 与 CompletableFuture基础语法和面向对象学完之后你可能会觉得代码写起来还是有些啰嗦。Java 8 引入的 Lambda 表达式和 Stream 流式编程能让代码简洁很多而 CompletableFuture 则是处理异步任务的重要工具。8.1 Lambda 表达式入门Lambda 的本质是一个匿名函数它允许你把行为作为参数传递。最经典的场景是匿名内部类的简化。以线程为例传统写法Runnable r1 new Runnable() { Override public void run() { System.out.println(传统写法); } };用 Lambda 简化后Runnable r2 () - System.out.println(Lambda 写法);再比如结合 Stream 对集合进行操作。现在有一组数字想过滤出大于 2 的并排序输出ListInteger numbers Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6); numbers.stream() .filter(n - n 2) .sorted() .forEach(n - System.out.println(n));这段代码的可读性明显比传统 for 循环加 if 判断要好。初学 Lambda 时把注意力放在语法格式上左边是参数列表-右边是方法体。当方法体只有一行时可以省略大括号和 return。8.2 方法引用与函数式接口方法引用是 Lambda 的一种简化写法。当 Lambda 体只是调用一个已经存在的方法时可以用类名::方法名或对象::方法名来代替。list.forEach(System.out::println);这等价于list.forEach(n - System.out.println(n));Java 8 还提供了一组函数式接口它们可以理解为 Lambda 表达式的类型常见的有PredicateT传入一个参数返回布尔值用于条件判断FunctionT, R传入一个参数返回另一个类型的结果ConsumerT传入一个参数没有返回值用于消费数据SupplierT没有参数返回一个值用于生产数据。理解这四类接口能帮你快速看懂常用的 Stream API 源码。8.3 CompletableFuture 异步编程CompletableFuture 是 Java 8 引入的异步编程工具可以用来编排异步任务。它的核心思路是把耗时的任务放到别的线程执行主线程不需要傻等任务完成后通过回调来通知结果。CompletableFuture.supplyAsync(() - { // 模拟耗时操作 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return 异步结果; }).thenAccept(result - { System.out.println(拿到结果: result); }); System.out.println(主线程继续执行不用等待异步任务);运行这段代码控制台会先打印主线程继续执行大约 1 秒后再打印拿到结果。这说明异步任务在后台线程中执行主线程没有被阻塞。这里有一个必须注意的坑supplyAsync默认使用ForkJoinPool.commonPool()公共线程池。在 Web 项目或高并发场景下公共线程池会被其他任务占用可能导致任务排队。生产环境中建议显式传入自定义线程池例如ExecutorService executor Executors.newFixedThreadPool(8); CompletableFuture.supplyAsync(() - 结果, executor);9. 常见报错与排查思路零基础阶段不可能不遇到报错。与其害怕报错不如学会利用报错信息来定位问题。下面列出几个自学阶段最高频的报错和排查思路。9.1 编译期错误与运行期错误的区别编译期错误发生在代码编译阶段IDE 会直接标红比如漏写分号、变量未声明、括号不匹配。这类错误很友好按照 IDE 提示修改即可。运行期错误发生在程序运行阶段编译能通过但执行到某行时报错。最常见的包括ArrayIndexOutOfBoundsException数组越界NullPointerException空指针调用了 null 对象的方法或属性ClassCastException类型转换异常NumberFormatException字符串转数字失败。排查运行期错误的核心方法就一条看异常堆栈。报错信息里的第一行是异常类型下面是调用栈从栈顶往下就是代码执行的路径。找到自己写的那个类名和行号问题基本就锁定一半了。9.2 源发行版 17 需要目标发行版 17报错这是 IDEA 中非常常见的一个编译警告完整信息类似java: 警告: 源发行版 17 需要目标发行版 17根本原因是 Maven 项目中的 Java 版本配置不一致。编译器源码级别是 17但目标运行级别没有同步设置。解决办法是在pom.xml中统一指定版本properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target /properties同时检查 IDEA 的File - Project Structure中Project SDK 和 Language level 是否一致。如果项目中混用了 JDK 8 和 JDK 17一定要统一否则就会出现各种版本相关的诡异报错。9.3 Lombok 编译器警告使用 Lombok 时部分同学会看到类似这样的警告java: You arent using a compiler supported by Lombok, so Lombok will not work with your project.原因是 Lombok 版本和当前 JDK 版本不兼容。Lombok 通过注解处理器在编译阶段生成代码当 JDK 升级后旧版 Lombok 可能无法识别新的编译器。解决办法有两个一是把 Lombok 依赖升级到支持当前 JDK 的最新版本二是在 IDEA 的Settings - Build, Execution, Deployment - Compiler - Annotation Processors中确认注解处理已开启。9.4 内存溢出 OutOfMemoryError当程序运行时内存不足JVM 会抛出java.lang.OutOfMemoryError。常见形式有Java heap space和insufficient memory。产生原因主要有三类堆内存配置过小程序需要的内存超过 JVM 默认分配代码中存在死循环或无限创建对象导致内存被快速耗尽存在内存泄漏对象无法被 GC 回收典型场景是静态集合不断添加元素。排查步骤如下使用jps查看 Java 进程 ID使用jmap -heap pid查看堆内存使用情况使用jstat -gc pid查看 GC 频率和内存变化重点检查代码中是否存在无限循环add到集合、缓存不清理等问题。对于零基础阶段更常见的是自己写着玩的代码出现死循环。排查时优先检查循环条件是否可能永远成立这比上工具分析快得多。9.5 报错排查思路汇总问题现象常见原因排查方向编译失败IDE 标红语法错误、缺分号、类型不匹配看 IDE 提示的第一处报错位置数组越界异常访问下标超出 length-1检查循环边界用 arr.length 控制空指针异常对象未初始化就调用方法在调用前打印对象是否为 null源发行版 17 需要目标发行版 17Maven 编译版本不一致统一 pom.xml 中的 source/targetLombok 不起作用Lombok 与 JDK 不兼容升级 Lombok 版本内存溢出堆太小或死循环创建对象检查循环和集合用 jmap 分析10. Java 基础面试八股文重点如果你学 Java 的目标是找工作那么从基础阶段开始就要有意识地积累面试考点。下面这些是 Java 基础面试中出现频率最高的内容暑假结束前建议全部能口述。10.1 基础语法高频考点和equals的区别是出现频率最高的题目。比较的是两个对象的内存地址equals是方法默认实现也比较地址但 String 等类重写了它改为比较内容。String、StringBuilder、StringBuffer的区别也是必考。关键点是 String 不可变StringBuilder 和 StringBuffer 可变StringBuffer 的方法加了 synchronized 锁线程安全但性能略低StringBuilder 线程不安全但性能更高。10.2 面向对象高频考点重载和重写的区别一定要区分清楚。重载是同一个类中方法名相同、参数列表不同与返回值无关重写是子类重新实现父类的方法方法签名必须一致。抽象类和接口的区别要能说出至少三点。抽象类可以有构造方法和成员变量接口在 JDK 8 之前只能有抽象方法和常量一个类只能继承一个抽象类但可以实现多个接口抽象类强调是什么接口强调能做什么。10.3 集合与并发高频考点ArrayList 和 LinkedList 的区别ArrayList 基于动态数组查询快、增删慢LinkedList 基于双向链表增删快、查询慢。HashMap 的底层原理是面试重灾区。JDK 8 中HashMap 底层是数组加链表当链表长度超过 8 且数组长度大于等于 64 时链表会转为红黑树。key 的 hash 值经过扰动运算后定位到数组下标哈希冲突时使用链地址法解决。volatile和synchronized的区别、ThreadLocal的原理这些并发问题可以留到进阶阶段再深入但基础阶段可以先记住结论。11. 学习笔记模板与工程建议学习过程中笔记是必须的但这不意味着要写一份漂亮的 Markdown 文档。我建议你用一个 GitHub 仓库管理学习笔记每个知识点一个文件格式固定方便回顾。11.1 笔记整理模板推荐每个知识点的笔记包含这五部分# 知识点名称 ## 一、核心概念 用一段话解释这个知识点是什么解决什么问题。 ## 二、代码示例 粘贴自己实现并运行成功的代码注明运行结果。 ## 三、易错点 记录自己踩过的坑、写错的代码、报错信息。 ## 四、面试考点 这个知识点在面试中可能怎么问参考答案要点。 ## 五、延伸思考 和它相关的其他知识点后续可以深入研究的方向。这个模板的价值在于它会逼着你不仅仅是抄代码而是用自己的话总结概念并且记录真实的踩坑经历。面试前复习自己的笔记本效率远高于重新翻视频。11.2 代码规范建议零基础阶段就要养成好习惯否则后面改起来很痛苦。类名使用大驼峰方法名和变量名使用小驼峰常量使用全大写加下划线方法要短一个方法只做一件事超过 30 行就考虑拆分变量名要有意义不要用a、b、c这种无意义命名代码格式化用 IDE 自带的快捷键不要手动调空格每个类文件顶部写清类的用途关键业务逻辑写注释说明为什么这样做。11.3 暑期自学避坑清单最后整理一份避坑清单都是零基础阶段比较高发的学习问题不要只看视频不写代码。视频是别人的经验代码才是你的能力。不要跳过环境搭建直接看语法。环境配置看起来枯燥但它能帮你理解 Java 的运行机制。不要遇到报错就复制粘贴搜答案。先自己读异常信息哪怕读三分钟也比直接抄答案收获大。不要一口气买好几本书。零基础阶段一本入门书加一套视频加一套练习题就足够了。不要拿收藏了等于学会了骗自己。收藏夹一周内不看就直接删掉。不要急着学 Spring 等框架。基础没打牢就学框架出了问题根本不知道是框架的锅还是自己的锅。如果你准备在这个暑假开始学 Java我的建议是不要纠结先学哪门语言、要不要报培训班更不要花时间比较几十套教程的优劣。选定一套路线从装好 JDK、写完第一个 Hello World 开始。遇到报错就停下来把异常信息读明白再继续往下走。两个月后回头看你会发现自己已经能读懂很多网上的 Java 项目源码了。动手永远比收藏教程更有用。这个暑假希望你也能亲手写出属于自己的第一个 Java 项目。