先说明一下:这个标题“javaDay03”很有意思。它不像“Spring Boot集成RocketMQ实战”那样目标明确,也不像“Java面试题汇总”那样一眼就知道内容边界。它更像是一个学习计划里的某个节点,比如某个培训营、某份学习路线图上的第三天。项目正文和关键词留空,反而是给了一个发挥空间:结合标题背后的热词分布,我能看到大量Java基础、面试题、环境配置、运算符表达式、面向对象之类的高频搜索。所以这篇文章我会把它定义成“零基础入门Java,第三天该学什么”的经验梳理,同时把热词里那些容易被忽略的坑(比如 Lombok 编译器警告、源发行版 17 报错、数组越界、JD-GUI 反编译乱码)串进去,让它既是一篇学习笔记,也是一份避坑手册。
1. “Day03”到底该学什么:一张学习路线图上的精确坐标
我自己带过不少转行的人,也看过网上几十份Java学习路线图,发现一个共同问题:Day01、Day02 的规划都特别清晰,装环境、配变量、写 HelloWorld、学变量和数据类型,但到了 Day03 就开始乱套。有人第三天就冲去学 Spring Boot,有人第三天还在折腾 JDK 版本,有人第三天已经开始刷“Java面试八股文”了。这其实是学习路线图最典型的断档期。
如果按绝大多数成体系的教学大纲来排,Day03 的坐标应该落在“运算符、表达式、流程控制”这一块。理由非常朴素:Day01 你搞定了 JDK 安装和环境变量,能跑通 javac 和 java 命令;Day02 你认识了变量、基本数据类型、标识符命名规则,知道int age = 18;这行代码在干什么;那 Day03 自然要回答下一个问题——“光有变量还不够,怎么让变量之间做计算、做判断、做重复操作?”这就是运算符和表达式的领域。
热词里有两个非常扎眼的搜索词:java运算符和表达式和java中数组越界异常。前者说明大量学习者卡在这一天,后者说明很多人刚写完数组相关代码就踩了运行时异常。这两个词放在一起,恰好印证了 Day03 的学习内容必然要延伸到数组的遍历和下标控制。所以我的建议是,Day03 的知识边界这样画:
- 核心:算术运算符、赋值运算符、关系运算符、逻辑运算符、三元运算符
- 延伸:运算符优先级、类型转换(自动转换与强制转换)
- 初步接触:if/else 分支、switch 分支、for/while 循环
- 实战触点:用循环 + 分支做一个小程序,顺带第一次接触数组的遍历
这套边界的好处是:Day04 学数组和二维数组时不会觉得突兀,Day05 学方法时已经能写出带逻辑的调用,Day06–07 进入面向对象之前,你已经有了“用代码描述流程”的体感。
还有一点必须提:这个阶段千万别急着碰框架。热词里一堆人搜java springboot apikey 安全对接、es异步写入java、qwen embedding、并存储milvus 调用示例 java langchain4j,这些对于 Day03 的学习者来说属于降维打击。不是说你学不会,而是基础语法没形成肌肉记忆之前,框架报错你根本没法定位是业务问题还是语言问题。我们做技术的最怕的不是报错,而是不知道错误属于哪一层。Day03 的使命,就是把这个分层的敏感度养出来。
2. 运算符优先级:初学者第一张“事故多发图”
2.1 从一道改错题的现场讲起
我带过的学员里,几乎每三个人就有一个在第三天写出类似这样的代码:
int a = 5; int b = 10; boolean result = a + b > 12 && a - b < 0; System.out.println(result);问他输出什么,有人愣半天,有人脱口而出“true”。为什么?因为他把a + b和a - b当成了一个整体,觉得是先算加法再算减法,然后再跟 12 和 0 比较。实际上 Java 里的运算顺序是:先算a + b得到 15,再算a - b得到 -5,然后依次做15 > 12(true)和-5 < 0(true),最后用短路与&&连接,输出 true。这在结果上碰巧是对的,但理解路径完全错了。真正危险的场景是:某天你写了一个复杂的库存扣减条件,因为优先级理解错误,线上数据直接错乱。
Java 运算符优先级不需要死记硬背全部表格,但有几个“事故高发区”必须刻进脑子里:
- 算术运算符高于关系运算符,关系运算符高于逻辑运算符。所以
a + b > 12 && a - b < 0实际的优先级顺序是:先算加减,再算>和<,最后算&&。 &&和||是短路运算符。左边已经能决定结果时,右边根本不会执行。false && 表达式里右边的表达式不会运行,true || 表达式里右边同样不会运行。这个特性在后续写判空逻辑时极其有用,比如if (list != null && list.size() > 0),一旦 list 是 null,短路能让后面的list.size()压根不执行,避免空指针。- 赋值运算符优先级极低,几乎最后执行。
int result = a + b;的顺序一定是先算右边的表达式,再赋给左边变量,而不是反过来。 - 三目运算符
条件 ? 表达式1 : 表达式2的优先级仅高于赋值运算符,低于逻辑运算符。这意味着true || false ? 1 : 2会被解析成(true || false) ? 1 : 2。
2.2 优先级的安全打法:用括号物化你的逻辑
我在实际开发里有一条铁律:凡是混合了三种以上运算符的表达式,一律加括号,哪怕我自己清楚优先级。这不是懦弱,而是可读性策略。代码首先是写给人看的,其次才是写给机器跑的。你写if ((a + b) > 12 && (a - b) < 0),任何一个路过的同事都不用去查优先级表,扫一眼就知道你的意图。
热词里还有一条值得注意:java comparator.comparing 将某元素值放第一个。这玩意儿虽然属于集合排序的范畴,但底层逻辑依然绕不开比较运算符。Comparator.comparing允许你指定排序字段,然后把某个特定值排到第一个,写起来通常是:
list.sort(Comparator.comparing(User::getStatus, (s1, s2) -> { if ("VIP".equals(s1)) return -1; if ("VIP".equals(s2)) return 1; return s1.compareTo(s2); }));这里的三目运算符和比较逻辑,本质上就是 Day03 学的那些基础能力在 JDK 8 新特性里的应用。你现在用三天打的基础,后面会像乐高积木一样拼出各种高级玩法。
2.3 一个容易误导人的细节:自增自减
i++和++i是初学者必踩的坑,也是面试官最爱问的基础题。记住两条实在的判断标准:
i++是“先用后加”:把 i 当前的值塞进表达式参与计算,然后再把 i 加 1。++i是“先加后用”:先把 i 加 1,再把新值塞进表达式参与计算。
来看典型例子:
int i = 3; int a = i++; // a = 3,i 变成 4 int b = ++i; // i 先变成 5,再赋值给 b,b = 5 int c = a++ + ++b; // a 当前是 3,用完之后 a=4;b 先变成 6,再参与加法;c = 3 + 6 = 9这种题在笔试里出现的频率很高,但我不建议用“记口诀”的方式去背,而是建议你在 IDE 里写一个小 Demo,用断点或者System.out.println一行行看变量的变化。你亲眼看到变量在每一步的值,比背十句口诀都管用。
提示:自增自减单独成行时,
i++和++i没有任何区别。它们只在参与表达式时才展现出顺序差异。所以别写int result = i++ + ++i;这种代码去秀操作,真实项目里没人这么写,代码评审大概率直接打回。
3. 流程控制代码块:从“从上到下”到“看情况走”
3.1 if/else 的分支逻辑优化
顺序结构你已经会了——代码从上往下逐行执行。但现实世界不是线性的:你要根据用户角色展示不同菜单,要根据库存数量决定是否允许下单,要根据成绩分数输出不同评价。这些“看情况走”的场景,就是分支结构。
写 if/else 最常见的问题不是不会写,而是写了一坨嵌套地狱:
if (score >= 90) { if (score == 100) { System.out.println("满分"); } else { System.out.println("优秀"); } } else { if (score >= 60) { System.out.println("及格"); } else { System.out.println("不及格"); } }这段代码能跑,但可读性很差。更好的做法是平铺直叙:
if (score == 100) { System.out.println("满分"); } else if (score >= 90) { System.out.println("优秀"); } else if (score >= 60) { System.out.println("及格"); } else { System.out.println("不及格"); }注意一个细节:score == 100一定要放在score >= 90前面。if/else 是“谁先满足谁先执行”,一旦score >= 90在上边,分数 100 的人就会先命中score >= 90,永远走不到满分分支。这种顺序问题在真实业务里特别常见,尤其是判断条件有包含关系时,必须把范围更小的条件放前面。
3.2 switch 新特性:从“贯通陷阱”到箭头语法
传统 switch 有个非常坑的语法:case 穿透。如果你漏写 break,代码会继续往下执行下一个 case,直到遇到 break 或者整个 switch 结束。这种设计在 C 语言时代是为了效率,但在 Java 里坑了无数人。
好在 Java 14 之后有了正式的 switch 箭头语法,不再需要手动 break:
String grade = switch (score / 10) { case 10, 9 -> "优秀"; case 8 -> "良好"; case 7 -> "中等"; case 6 -> "及格"; default -> "不及格"; };箭头右边的表达式执行完自动结束,不需要 break,而且还能直接把值赋给变量。这个写法在热词java基础的搜索群体中其实已经不算新知识了,但实际项目中很多老项目还在用传统冒号写法,所以你在阅读老代码时依然要能看懂透传行为。两种写法都要会,新代码尽量用箭头语法。
3.3 for 循环的精确套路:从头写明边界
循环是让代码变得强大的第一步。for循环有三段式结构:
for (初始化; 布尔条件; 更新) { // 循环体 }最经典的遍历数组写法:
int[] numbers = {10, 20, 30, 40, 50}; for (int i = 0; i < numbers.length; i++) { System.out.println(numbers[i]); }这里有两个容易出的问题:
第一,边界条件写错。i <= numbers.length一定数组越界,因为数组下标从 0 开始,最后一个元素的下标是length - 1。热词里专门有java中数组越界异常,说明这个错误已经不是一个两个人的问题了。ArrayIndexOutOfBoundsException 和 NullPointerException 并列,是 Java 初学者最常遇到的两大运行时异常。
第二,循环变量的生命周期。for (int i = 0; ...)里的i只在循环体内有效,循环结束后再访问i会编译报错。这是 Java 变量作用域的设计。如果你需要在循环结束后拿到某个状态,就把变量定义在循环外面。
3.4 while 与 do-while 的节奏感
while循环是先判断后执行,可能一次都不执行;do-while是先执行后判断,至少执行一次。这个差异在实际开发里非常实用。比如读取用户输入直到输入 q 退出,如果你用 while 就得先读一次再判断,代码很别扭;用 do-while 就自然很多:
Scanner scanner = new Scanner(System.in); String input; do { System.out.print("输入指令(q退出):"); input = scanner.nextLine(); // 处理指令 } while (!"q".equals(input));这种先执行再判断的逻辑,天然适合“至少要执行一次”的业务场景。
3.5 死循环的正确用法与优雅退出
初学阶段老师会告诉你别写死循环,但真实项目里服务器主线程、消息消费者、游戏引擎主循环,全是死循环。区别在于死循环内部必须有退出条件和节奏控制:
while (true) { String command = receiveCommand(); if ("SHUTDOWN".equals(command)) { break; } process(command); Thread.sleep(1000); // 控制节奏,防止 CPU 空转 }break跳出当前循环,continue跳过本次迭代直接进入下一次。这两个关键字和return的区别要分清:break只管循环,continue只管本次循环,return直接结束整个方法。
4. 用 IDE 的断点调试和数组案例,把语法的“死知识”变成肌肉记忆
4.1 一个综合小项目:评委打分程序
说了这么多语法规则,是时候上手练了。我强烈建议 Day03 当天完成一个“评委打分”小程序,需求如下:
- 用数组存储 5 个评委的分数(整数即可)。
- 计算总分、平均分。
- 找到最高分和最低分。
- 计算“去掉一个最高分和一个最低分后的平均分”。
这个需求几乎覆盖了 Day03 的全部重点:数组声明显式初始化、循环遍历、关系比较、变量累加、if 分支更新最大值最小值。下面给一个参考实现:
public class ScoreCalculator { public static void main(String[] args) { int[] scores = {88, 92, 75, 96, 84}; int sum = 0; int max = scores[0]; int min = scores[0]; for (int score : scores) { sum += score; if (score > max) { max = score; } if (score < min) { min = score; } } double avg = (double) sum / scores.length; double avgWithout = (double) (sum - max - min) / (scores.length - 2); System.out.println("总分:" + sum); System.out.println("平均分:" + avg); System.out.println("最高分:" + max); System.out.println("最低分:" + min); System.out.println("去掉最高最低后的平均分:" + avgWithout); } }for (int score : scores)是增强 for 循环,也叫 foreach。它只用于从头到尾遍历,拿不到下标。需要下标时还是用传统的for (int i = 0; ...)。
第 12 行有个关键细节:(double) sum / scores.length是先把sum强制转换成 double,再除以 int,结果是 double。如果不转换,整数除以整数还是整数,平均分直接变成 85 而不是 87.0。这个类型转换的坑,几乎所有初学者都会踩一次。
4.2 断点调试才是 Day03 最该学会的终身技能
很多自学者学到语法但不学调试,导致写错代码只能靠一遍遍加System.out.println。这当然能解决问题,但效率低。我更推荐在你刚学循环和分支的时候就用 IDE 的断点调试功能。
步骤极其简单(我以 IntelliJ IDEA 为例):
- 在
for循环那一行的行号右侧点一下,出现一个红点,这叫断点。 - 点击右上角的 Debug 按钮(绿色甲虫图标)。
- 程序运行到断点处暂停,IDE 底部弹出 Debug 窗口。
- 按 F8(Step Over)单步执行,可以看到
i、score、sum、max、min的实时值。 - 按 F9(Resume Program)跳到下一个断点。
用断点看变量变化,你的思维模式就变了。你不是在“猜”代码怎么执行,而是在“看”代码怎么执行。这个能力比任何语法书都管用,后面学递归、学集合源码、学并发,全靠它。
4.3 学习中的“刻意练习”节奏
Day03 不建议做海量重复题。我推荐“1 + 3”法则:1 个综合案例(评委打分)+ 3 个知识点复盘题目。复盘题目不用多,但要精准:
- 写一个程序,输出 1 到 100 之间所有能被 3 整除但不能被 5 整除的数。这个题练的是取模运算符
%和 for 循环的组合。 - 用 while 循环实现输出斐波那契数列前 10 项。练的是循环内变量交换的经典手法。
- 写一个简易菜单,用 switch 根据用户输入的数字执行不同操作,直到输入 0 退出。练的是嵌入式交互逻辑。
这三道题做完,你的 Day03 已经从“听懂”走向“会写”。注意,这里的“会写”标准是:不查资料、不看笔记,从空文件开始独立敲出来。敲不出来就回头再看笔记,再敲,直到能独立完成。
5. 常见环境与编译器报错:第三天最容易卡住的四个坑
热词清单里藏着好几个高频报错,这里集中梳理一下,免得你在这上面浪费时间。
5.1 “源发行版 17 需要目标发行版 17”是什么意思
这个报错本质上是项目编译的字节码版本和当前 IDE 或 Maven 配置不一致。你电脑上装的 JDK 可能是 17 或更高,但项目设置里 Java Compiler 的 target 版本没跟上,或者 Maven 的maven.compiler.source/maven.compiler.target没配置。解决方案通常是三处对齐:
File -> Project Structure -> Project里的 SDK 版本。File -> Project Structure -> Modules里每个模块的 Language Level。- Maven 的
pom.xml里设置<maven.compiler.source>17</maven.compiler.source>和<maven.compiler.target>17</maven.compiler.target>。
我见过很多学员明明装的是 JDK 21,但 IDE 默认 Language Level 还是 8,编译完还是报错,就是这三处没对齐。
5.2 Lombok 的编译器警告:lombok will not work
热词里有一条:java: you aren't using a compiler supported by lombok, so lombok will not wo。Lombok 是个编译期注解处理器,通过修改编译流程来生成 getter、setter、builder 等方法。如果你的 IDE 里 Lombok 插件缺失、或者项目使用了过新的 JDK、又或者注解处理器没开启,Lombok 就罢工,然后代码里所有@Getter、@Data注解的地方全部报“找不到符号”。
检查顺序:确认 IDE 装了 Lombok 插件 -> 确认pom.xml或 Gradle 里引入了对应依赖 -> 确认Settings -> Build -> Compiler -> Annotation Processors里 Enable annotation processing 勾上了。这三步解决九成问题。如果你是 JDK 21 遇到兼容性问题,尽量选择最新版 Lombok。
5.3 JD-GUI 反编译乱码
搜jdgui反编译后的java文件,带有注释符号,快速去除的人,多半是拿到了一个 jar 包,想反编译看源码,结果注释乱成一团。遇到这种问题,别急着在 JD-GUI 里折腾,先把 jar 包改名成 zip 解压,再用 IDE 直接打开源码目录,配合Ctrl + Shift + R全局搜索,效率更高。反编译的源码只能作为参考,不能作为 review 依据,因为编译器优化会让局部变量名失真。
5.4 数组越界的定位技巧
当你的程序抛出java.lang.ArrayIndexOutOfBoundsException时,错误信息通常长这样:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5重点看冒号后面的内容:Index 5说明你访问了下标 5,length 5说明数组长度只有 5,合法下标是 0 到 4。所以问题就是你写出了访问第 6 个元素的代码。然后根据堆栈信息定位到具体行,检查循环条件是不是用了<=而不是<,或者数组声明和遍历的边界不匹配。
6. Day03 学完之后,怎么和后面的“面向对象”衔接
6.1 为什么要在这里停下来想“方法”
热词里面向对象编程java的热度一直很高,但面向对象不是从天而降的概念。当你写完评委打分程序后,你会发现一个问题:如果以后我要对多个评委数组打分,是不是要把主方法里的代码复制粘贴好几遍?复制粘贴是最初级的复用手段,但代码一多就变成灾难。这个痛苦的瞬间,就是理解“方法”的绝佳时机。
Day03 的最后,我建议你尝试把评委打分功能改造成一个方法:
public class ScoreCalculator { public static double averageWithoutMaxMin(int[] scores) { int sum = 0; int max = scores[0]; int min = scores[0]; for (int score : scores) { sum += score; if (score > max) max = score; if (score < min) min = score; } return (double) (sum - max - min) / (scores.length - 2); } public static void main(String[] args) { int[] scores1 = {88, 92, 75, 96, 84}; int[] scores2 = {70, 80, 90, 65, 85}; System.out.println(averageWithoutMaxMin(scores1)); System.out.println(averageWithoutMaxMin(scores2)); } }这不就实现了代码复用吗?方法就是一段有名字的代码块,可以接受参数、返回结果。后面你再学类,其实就是把一堆相关的方法和属性打包成一个对象模板。所以 Day03 的终点看似是循环和分支,实际上是为 Day04 的方法、Day05 的类与对象铺路。这就是学习路线的节奏感:每个知识点不孤立存在,而是下一个知识点的引子。
6.2 练习量多少算够
我见过不少人在第三天疯狂刷题,一天做上百道,结果第四天学方法时全忘了。因为题海战术只训练了短期记忆。第三天更重要的是建立“看到一个问题,能拆解成输入、处理、输出三层”的思维方式。哪怕只写了五六十行代码,只要这三层逻辑清晰,第四天的学习速度会明显加快。
如果你已经完成了评委打分程序,再试着做一个小升级:把评委人数改成控制台输入,分数也由用户逐个输入。这就会自然牵扯到你之前学的 Scanner 类、nextInt()方法,甚至要考虑输入非法字符的异常情况。这个升级就能把你从“语法学习者”拉向“问题解决者”。
6.3 Day03 结尾的一点个人经验
每次带新人,我都会说第三天是一个分水岭。前两天的内容不管基础多差都能跟得上,因为变量和类型就像认字。但第三天开始你真正接触逻辑——分支、循环、运算符、调试,这些才是编程的“肌肉记忆”时刻。你能不能在计算机行业待下去,往往不是看你会不会背八股文,而是看你能不能耐心地单步调试一段循环,找到那个让数组越界的边界条件。
热词里有大量java面试八股文和java面试题的搜索,说明大家很焦虑面试。但所有的面试题,最终都绕不开这些基础能力。你可以在面试前刷八股文,但把一个 Day03 的小逻辑用 Debug 方式彻底看透所带来的底气,是任何背诵都给不了的。第三天的任务,说白了就一句话:多写、多调、多问为什么,把这几个语法点变成你自己的腿脚,第四天才能跑起来。