如果你是零基础开始学Java第一天搞定了JDK安装、环境变量配置、写下了人生第一行Hello World那么Day02就是真正开始“变程序员”的一天。这一天学的所有东西——变量、数据类型、运算符、流程控制——都套路固定、信息量大却是往后所有项目的地基。我把培训班的第二天课程结合自己实际踩过的坑整理成这篇笔记不管你是自学的、跟着视频课的还是在课堂上听的都可以参照这个节奏走。这篇内容适合把Java当第一门语言的新手也适合学过但基础不稳、回来补地基的同学。Day02的目标只有一个让程序能根据不同情况做不同的事而不是永远从上到下执行完就结束。1. Day02到底学什么1.1 第一天之后你该掌握什么开始说第二天之前先花一点时间对一下第一天的位置。如果Day01只是照着视频敲了一遍HelloWorld、老师敲一行你敲一行那建议不要急着往下冲。Day02的所有内容都建立在一个很基础的前置条件上你能够用命令行或者IDE手动创建一个.java文件编译出.class文件然后运行它并且你能分清下面这三行命令各自干了什么javac Hello.java java Hellojavac是编译java是运行。很多新手第一天栽就栽在把这两个命令混为一谈或者编译成功了却忘了自己是不是真的在同一目录下执行。Day02开始之后代码行数会从一行变成几十行一旦连文件管理都是乱的报错排查会加倍痛苦。如果你已经做到了“自己能独立写完并跑通HelloWorld”那就可以放心进入Day02的主线了。1.2 第二天的主线让程序学会“思考”第一天的HelloWorld本质是直线程序——从第一行执行到最后一行程序没有任何判断。Day02要打破的正是这个单线模式。这一天的核心内容可以概括成四块变量与数据类型程序里怎么存数据运算符数据之间怎么计算流程控制程序怎么根据条件走不同的路小项目实操把前三块串起来写一个完整的小程序四块内容环环相扣。变量不会运算符就是空中楼阁运算符不熟流程控制的分支和循环条件就写不出来流程控制不会后面数组、方法、面向对象全都寸步难行。所以Day02与其说是“学新知识”不如说是给整个Java学习打地基中的地基。1.3 为什么很多人卡在Day02坦白说Day02是培训班里第一天淘汰率最高的节点。不是因为难是因为它“不像编程”。HelloWorld还能让你有点“我写出程序了”的成就感变量和运算符这些内容却全是抽象规则——int是什么、double是什么、为什么1加1要写成1 1每一件事都像在学一门新语言的语法又看不到什么立竿见影的效果。我自己带的模拟项目里好几个零基础的同学都是在Day02觉得自己“是不是不适合学编程”。真相是Day02没有反馈感是正常的这个阶段本来就是在储备工具。真正让你有感觉的是Day02最后写的那个猜数字小游戏哪怕只有二三十行代码那也是你第一次写“看起来像个产品”的东西。2. 变量与数据类型程序的基本容器2.1 为什么要先分清数据类型变量可以理解成一个带名字的盒子你往里面放东西Java规定盒子本身要先写上“能放什么类型的东西”。这就引出了Java的一个重要特点强类型语言。意思是语法层面的规则非常严格什么类型存什么数据算之前必须规定清楚不适合的会直接报错。Java把数据类型分成两大类基本数据类型和引用数据类型。Day02阶段的主力是基本数据类型一共8种类型占用空间取值范围默认值byte1字节-128 ~ 1270short2字节-32768 ~ 327670int4字节约正负21亿0long8字节很大0Lfloat4字节大约7位有效数字0.0fdouble8字节大约15位有效数字0.0char2字节0 ~ 65535\u0000boolean不定true / falsefalse记忆的时候不需要死背字节数但有一个结论必须刻进脑子里日常写整数默认用int写小数默认用double。注意long类型的字面量需要在数字后面加L大小写都行建议大写float类型的字面量需要加F。不加的话小数默认被当成double整数默认被当成int精度不匹配会直接编译报错。2.2 变量命名规范与关键细节变量命名的规则有两层。一层是硬性规则违反直接就编译不过不能以数字开头不能使用Java关键字不能出现空格只能包含字母、数字、下划线和美元符号。另一层是软性规范违反了不报错但会被同事喷类名用大驼峰变量名和方法名用小驼峰见名知意。我见过一个很有意思的问题有人把变量命名为class直接编译报错因为class是关键字。还有人把变量命名为String这个居然没问题因为Java的关键字列表里没有它类名是区分大小写的但强烈建议不要这么干——自己看的都晕。变量使用的另一个重要细节是初始化。局部变量方法里定义的变量不像成员变量有默认值你不给它初始值就直接用编译器会直接拒绝。比如下面的代码int count; System.out.println(count); // 编译报错可能尚未初始化很多新手第一次看到这个报错会一脸懵我不是声明了吗对声明了但没赋值。Java要求局部变量在使用前必须明确赋值这是为了杜绝那种“不知道是什么值就把程序跑起来”的隐患。2.3 类型转换与常见错误类型转换分两种自动类型转换和强制类型转换。整型、浮点型、字符型参与运算时小范围类型会自动提升为大范围类型。int和double一起运算结果是double因为整数能无损变成小数反过来不行。这里有个高频坑整数除以整数得到整数。double result 5 / 2; System.out.println(result); // 输出2.0不是2.5原因在于5 / 2两个都是intint相除先算出int结果2再把这个2转成double变成2.0。想得到2.5必须让两个操作数里至少有一个是浮点类型比如5.0 / 2或者(double) 5 / 2。强制类型转换是从大范围往小范围转比如double转intint a (int) 3.99; // a 的值为 3直接截断小数部分不是四舍五入强制转换就像把一个double盒子里的水硬倒进int盒子里多的部分直接溢出或丢弃这种操作要心里有数尤其是在做数值计算的项目时精度丢失是常见bug来源。3. 运算符让数据产生关系3.1 算术与赋值运算符算术运算符有六个 - * / %外加一个字符串拼接用的。看起来简单实际上陷阱不少。字符串拼接的运算比较特殊System.out.println(年龄是 20 1); // 输出“年龄是201” System.out.println(20 1 岁); // 输出“21岁”原因在于从左往右结合。第一个表达式先拼接字符串“年龄是20”然后再拼上字符串“1”第二个表达式先做整数加法20121再和“岁”拼接。新手很容易在这种细节上翻车。赋值运算符除了还有 - * / %这一组复合赋值。a 1等价于a a 1先加减再重新赋回自己写起来简洁是实际开发里的高频写法。但复合赋值有一个隐藏细节它自带一次隐式类型转换。例如byte b 10; b b 1; // 编译报错int转byte可能丢失 b 1; // 编译通过相当于 b (byte)(b 1)这个知识点很多工作了两三年的人都未必说得清Day02就能理解的话后面看源码会省力不少。3.2 关系与逻辑运算符关系运算符 !的结果是boolean类型只有true或false。新手最容易在这类运算符上犯一个认知错误以为比较的是“内容一样”其实对于基本数据类型它比较的就是值本身对于引用类型它比较的是地址。Day02阶段先用基本类型去理解就好引用类型的比较问题留到面向对象再去深挖。逻辑运算符有 || !三个分别表示并且、或者、取反运算结果是boolean。和||都有短路特性左边为false右边就不执行||左边为true右边就不执行。短路特性有实际使用价值if (score ! 0 100 / score 10) { // 如果score是0右边表达式根本不会执行不会出现除零错误 }3.3 位运算与三元运算符Day02课堂上限不太会深入讲位运算但和|这两个符号以“逻辑运算符不短路的版本”出现时很多同学会疑惑。它们确实也能做逻辑运算区别是两边都会计算。日常业务代码里我建议统一使用和||短路的性能更好语义也更明确。三元运算符条件 ? 值1 : 值2相当于一个简化版if-elseint max a b ? a : b;翻译过来就是“a大于b吗成立取a否则取b”。这个表达式很简洁后面写算法题、写业务判断时出场率极高Day02阶段练习几次就能顺手。4. 流程控制程序的分岔路口4.1 if-else 分支结构掌握了变量和运算符之后程序终于可以“看情况办事”了。最简单的分支语法是if (条件) { // 条件成立执行 } else { // 条件不成立执行 }分支结构的贪心匹配原则是一个需要特别注意的坑else总是和最近的if配对。看下面这段代码int x 10; if (x 0) if (x 5) System.out.println(大于5); else System.out.println(不大于0);最后那个else到底属于哪个if语法上它属于内层if (x 5)不是外层if (x 0)。所以这个逻辑和“大于0且不大于5输出‘不大于0’”完全是两回事。少写大括号是这类bug的根源做不到每层if都加大括号的话就别怀疑编译器为什么总跟你对着干。if-else if-else多分支结构适合处理多个互斥的条件if (score 90) { System.out.println(优秀); } else if (score 80) { System.out.println(良好); } else { System.out.println(继续加油); }注意条件顺序有讲究。如果把 80放在前面90分也会先命中“良好”因为90同样满足 80。多分支应该从范围窄的条件往范围宽的条件写。4.2 switch 与穿透问题switch根据一个变量的值跳转到对应分支执行适合“一对一匹配”的场景switch (day) { case 1: System.out.println(周一); break; case 2: System.out.println(周二); break; default: System.out.println(未知); }case穿透是指匹配到一个case后如果没有遇到break会继续往下执行后续所有case的代码。这既是坑也是特性。有一些特殊场景会故意利用穿透比如多个case执行相同逻辑case 1: case 2: System.out.println(工作日开头); break;Day02阶段我建议老老实实每个case都写break等掌握得扎实了再去玩“故意穿透”的花活。switch支持的数据类型现在的Java已经覆盖了int、String、枚举和一部分包装类型基本够用。如果判断逻辑复杂用if更清晰如果就是单值匹配switch可读性更好。4.3 循环结构for、while、do-while循环让程序能重复执行某段代码。for循环适合固定次数的场景for (int i 1; i 10; i) { System.out.println(i); }for循环的执行顺序是初始化 - 判断条件 - 执行循环体 - 更新表达式 - 再判断。很多新手误以为先更新再判断结果调试死循环的时候找不到原因。while循环适合“次数不确定但条件明确”的场景int i 1; while (i 10) { System.out.println(i); i; }do-while和while的区别在于do-while至少执行一次int i 100; do { System.out.println(i); i; } while (i 10); // 还是会输出一次100实际开发中for和while出场最多do-while相对少但它有一个很实用的意义有些场景下你希望先验证一轮再说结论。循环里还有两个控制语句break直接跳出整个循环continue跳过当前这一轮循环的剩余代码、进入下一轮。这两个在写猜数字游戏时会用上。5. 一个能跑的Demo猜数字小游戏5.1 需求拆解与设计Day02的收尾项目最经典的就是猜数字。需求很简单程序随机生成一个1到100的整数用户反复输入猜测的数字程序提示猜大了还是猜小了猜中就结束。这个项目虽然小但把Day02的知识点全部串起来了生成随机数用Math.random()或Random类读取用户输入用Scanner对比数字大小用关系运算符反复猜的过程用循环猜中退出用break先想清楚流程再动手写代码这也是Day02最值得培养的习惯。拿到需求就闷头敲代码敲到一半发现逻辑理不清再回头看就一团乱麻。5.2 逐步实现直接用Random生成随机数用Scanner读取控制台输入。完整代码如下import java.util.Random; import java.util.Scanner; public class GuessNumber { public static void main(String[] args) { Random random new Random(); int target random.nextInt(100) 1; Scanner scanner new Scanner(System.in); while (true) { System.out.print(请输入你猜的数字1~100); int guess scanner.nextInt(); if (guess target) { System.out.println(猜大了); } else if (guess target) { System.out.println(猜小了); } else { System.out.println(恭喜猜对了); break; } } scanner.close(); } }random.nextInt(100)生成0到99的整数加1之后变成1到100。注意nextInt(100)的括号里是上限但生成范围是左闭右开也就是0到99不含100。每个环节都弄清楚为什么这样写后面遇到各种边界问题心里才有底。这个程序虽然短但已经包含了输入、输出、循环、分支和随机数的完整组合。跑通它之后建议你自己做几个小改动比如记录用户猜的次数输入0时提前退出超过一定次数直接揭晓答案。每加一个需求就多练一个知识点。5.3 代码走读与改进空间跑通之后的代码走读步骤同样重要。我从实际教学观察来看很多同学跑通后就没再看过这段代码但恰恰是走读才能真正提升。先说代码里的一个隐患scanner.close()会关闭底层输入流。在这个小程序里这样写没问题但如果在后面还要继续用Scanner读输入关闭之后再读就会报错。主流IDEA会提示这个操作存在风险早期阶段直接用即可但要记住这个行为。另一个改进方向是循环结构的选择。这里用while (true)加break退出也可以用一个boolean变量控制循环boolean isCorrect false; while (!isCorrect) { // ... if (guess target) { isCorrect true; } }两种写法都可以while (true)更直接boolean变量控制更符合结构化编程的审美。Day02阶段两种都试试感受一下不同写法的可读性差异比死记硬背“哪个更好”有意义得多。再加一个锦上添花的需求记录猜测次数。int count 0; // 每次循环 count // 猜中后打印 count这能让你直观感受到变量在循环中如何累积是理解循环和变量关系的最佳训练。6. 这两天最值得记住的避坑清单6.1 高频编译报错与解决Day02的报错大概集中在这么几类先看清楚报错信息再动手改报错信息含义常见原因程序包不存在 / 找不到符号编译器找不到某个类或变量忘记import、变量名写错、字母大小写不一致可能尚未初始化变量变量没赋值就使用了漏写了初始化不兼容的类型类型转换有问题int赋给double可以double赋给int不行缺少返回语句方法需要返回值但代码路径缺失if分支里return了else里没写意外的类型表达式类型不合法给表达式赋值比如(a b) 10排错的第一原则看第一行报错不要从最后一行开始看。控制台输出里第一行往往直接告诉你出错的文件、行号和原因。很多同学一看到一长串异常就直接慌了实际上一行一行读大部分问题自己就能找出来。第二原则编译报错的位置不一定就是真正出错的位置。有时候错误在它之前的几行因为括号没闭合导致解析器把后面的代码解析错了。6.2 新手最容易误解的语法点一个标志性的坑就是中文符号问题。Java要求所有标点都是英文半角符号好多新手第一天用中文输入法打字随手打出一个中文分号“”编译器立刻给出“需要;”的报错。这种问题没法用眼睛快速发现所以第一反应应该是去检查出错行的标点符号是否用的是英文。还有一类问题是主方法签名。public static void main(String[] args)这行字多容易打错。少了public程序还能运行少了static在某些环境下不行String[]写成string[]直接报错。建议每次新建类时先敲这行签名再写其他内容形成肌肉记忆。if、for、while的大括号匹配错误也极其高频。Day02的代码量不大我建议初期养成“写左括号的同时立刻写右括号然后光标移回括号中间写代码”的习惯能在源头上避免一类错误。后面代码量大了IDE的自动补全也会帮你配好括号但习惯还是尽早建立比较好。6.3 练习建议与学习节奏Day02结束后建议再做几个由易到难的练习来验证自己是不是真的吸收了判断一个整数是奇数还是偶数输出1到100之间所有3的倍数计算1加到100的和输入一个月份数字输出对应季节打印九九乘法表这些题不需要任何新知识纯粹是变量、运算符、流程控制的组合练习。如果每道题都能不看参考答案独立完成Day02就算真正过关了。节奏上不要追求一天做完全部题目质量比数量重要。第5题九九乘法表要嵌套两层for循环对新手来说是很好的思维训练建议多花点时间琢磨。最后说点我自己的体会每次带模拟项目我都会跟同学强调一句话Day02不是用来“看懂”的是用来“敲熟”的。变量名记不住没关系常用就行。运算符优先级记不住没关系多写几遍自然就顺了。真正要注意的是不要眼高手低——视频里老师讲得再明白你觉得自己懂了关掉视频自己从头写一遍立刻就知道自己哪里没通。如果你发现这一天内容有点吃力不要怀疑自己不行先回到报错信息里去回到每一个“为什么这里要用int”“为什么这里要加break”这种小问题上去。把这些小问号一个个拉直Java的地基就一点点打牢了。Day02的尽头不是学会多少语法而是你第一次发现自己居然能设计一个小程序的流程逻辑那种感觉很微妙也很上瘾。后面Day03通常会进入数组和方法那时候你回头再看今天写的猜数字游戏会发现自己瞬间就能看懂那些代码甚至能顺手优化掉一两个变量。地基塌不塌就看Day02这节课走得实不实。