如果你正在看这篇文字,大概率已经在网上翻了半天“java入门”相关的帖子了。我见过太多人学 Java 的第一天,不是被语法难倒,而是被环境配置劝退:下载安装包、设置环境变量、敲java -version结果报错,还没写一行代码就放弃了。这篇文章是 JAVA 入门系列的第 01/23 节,作用就是把这一关彻底趟平。今天你会弄清楚 Java 到底是什么、开发环境怎么装、第一个 Hello World 怎么跑通,以及变量、数据类型、标识符命名规则这些最基础的语法。学完这一节,你对 Java 会有一个完整但简单的轮廓,后面 22 节课就都是在往这个骨架里填充血肉。
1. 第 01/23 节到底学什么:先弄清 Java 的定位
1.1 Java 是一门什么样的语言
严格来讲,Java 是一门静态类型、面向对象的编程语言,写好的代码交给 Java 虚拟机(JVM)运行。这句话可以拆成三部分来理解。
静态类型,意思是变量在声明的时候就必须告诉编译器它是什么类型,不能像某些脚本语言那样随意切换类型。面向对象,意思是程序设计围绕“类”和“对象”来展开,一个 Java 文件里几乎总能看到class关键字。运行在 JVM 上,意思是它不像 C/C++ 那样编译完直接生成针对特定 CPU 的机器码,而是生成一种叫做“字节码”的中间产物,再由 JVM 解释执行。
用大白话类比:C 语言像是一个人直接用方言跟电脑对话,Java 则是先把人话翻译成一种统一的“世界语”(字节码),然后每个操作系统各配一个翻译官(JVM),不管是 Windows、Linux 还是 macOS,翻译官都能把世界语翻译成当地系统听得懂的话。这就是 Java 号称“一次编写,到处运行”的底层逻辑。
不过第一天不需要把这些原理吃透,你只需要记住一个核心结论:Java 代码不是直接给操作系统执行,而是给 JVM 执行。这个认知会帮你解释后面遇到的大多数奇怪现象。
1.2 学 Java 的现实用途与 23 节课程地图
很多人犹豫要不要学 Java,一看网上“Java 凉了”的论调就慌。从我接触过的项目看,Java 目前依然是后端开发的中坚力量。电商系统的订单服务、支付网关、企业里的 ERP 和 OA、大数据生态里的 Hive 和 Flink,底层大量都是 Java;安卓开发的主力语言虽然变成了 Kotlin,但 Kotlin 也跑在 JVM 上,懂 Java 再学 Kotlin 几乎是无痛切换。可以说,只要你想走企业级开发这条路,Java 依旧是投入产出比很高的选择。
这也解释了为什么本系列要拆成 23 节课。整个规划不是随便排的,而是按照“先能跑、再懂语法、然后深入原理、最后做项目”的递进来安排的,具体地图如下:
| 课程范围 | 核心内容 | 学完能做什么 |
|---|---|---|
| 第 01 节(本节) | 环境搭建、Hello World、基础语法 | 能独立运行第一个 Java 程序 |
| 第 02-08 节 | 流程控制、方法、数组、面向对象 | 写出带逻辑的简单小工具 |
| 第 09-15 节 | 常用类库、异常、集合、泛型、IO | 处理文件读写、字符串、数据容器 |
| 第 16-20 节 | 多线程、网络编程、反射、JVM 基础 | 理解并发编程,能排查简单性能问题 |
| 第 21-23 节 | 实战项目与面试题解析 | 能串起全部知识,应对初级面试 |
这张地图想说明一件事:Java 的知识量确实不小,但每个阶段都有清晰的验收标准。不要想着一天看完 23 节,那不是学习,是浏览目录。第一节只负责打好地基,地基稳了,后面才有加速度。
1.3 本节课结束后的验收标准
学完今天这节,你应该能做到这几件事,做到了就算过关:
- 能用自己的话说清楚 JDK、JVM、字节码分别是什么。
- 能从零写出一个 Hello World 程序,并成功运行看到输出。
- 知道 Java 有哪八种基本数据类型,以及
int和long的区别。 - 能写出符合规范的变量名和类名,并且知道为什么
1abc这种写法会报错。
如果这四点都没问题,今天就可以休息了。下一节我们再开始接触流程控制和逻辑判断。如果哪一点卡住了,重点回到对应的章节再敲一遍,编程这件事,动手永远比看懂重要。
2. 环境搭建这一关:JDK 选择、安装与环境变量原理
2.1 先分清 JDK、JRE、JVM 三个东西
环境搭建的第一步是下载一个叫 JDK 的东西,但很多人装完之后还是一头雾水:JDK、JRE、JVM 长得像三兄弟,到底什么关系?
我用一句话概括它们的关系:JDK 包含 JRE,JRE 包含 JVM。JDK(Java Development Kit)是开发工具包,给写代码的人用的,里面除了运行环境,还带了javac编译器、jar打包工具、javadoc文档工具等;JRE(Java Runtime Environment)是运行环境,给只跑程序的人用的,普通用户装了这个就能运行 Java 程序;JVM(Java Virtual Machine)是 Java 虚拟机,负责真正执行字节码。
打个比方,JDK 是一间完整的厨房,里面有锅(编译器)、有灶(运行环境)、还有洗碗机(各种工具);JRE 是只吃饭的餐厅后厨,只有灶台没有厨师工具;JVM 是那个燃气灶本身。你学开发必须装 JDK,因为你需要javac这个“锅”来把源码炒成字节码。如果只装了 JRE,你能跑别人做好的程序,但自己写不了。
2.2 版本选择:别盲目追新,看行业需求
选版本是新手最常见的纠结。下载页面一堆数字,8、11、17、21,选哪个?我的建议很简单:
- 如果是纯学习、想体验新语法,装 Java 17 或 21 都行,它们是长期支持版本(LTS),稳定性有保证。
- 如果是为了配合找工作、看公司存量项目,Java 8 仍然大量存在于企业生产环境中,学了完全不亏。
- 不建议装刚发布的非 LTS 版本,比如 Java 23 这种,虽然新特性很多,但生态里的框架未必跟得上,学了容易踩兼容性坑。
具体下载时,我个人推荐选 Eclipse Temurin 或者 Oracle JDK 都行,前者是社区维护的 OpenJDK 构建版,免费且没有任何使用限制的顾虑,后者是官方原版。下载页面上认准对应操作系统的安装包,Windows 选.exe或.msi,macOS 选.dmg,Linux 选.tar.gz。
还有一点容易忽略:下载前先确认系统是 64 位还是 32 位。现在基本都是 64 位系统了,但如果你还用着老机器,下载错了会直接提示“不是有效的 Win32 应用程序”,浪费半天时间。
2.3 安装 JDK 的完整操作
安装过程本身没什么玄学,双击安装包一路 Next 就行,但我建议你做两件默认安装不会做的事。
第一,记住你的安装路径。默认路径一般是C:\Program Files\Java\jdk-17,后面配置环境变量需要用到,如果忘记可以回安装目录去看。我见过有人图省事直接装在默认位置,也能用,但路径里有空格和中文的时候,某些老工具会莫名出错。如果条件允许,装到D:\Java\jdk-17这种没有空格和中文的目录,能省掉很多后续麻烦。
第二,不要勾选公共 JRE。新版 JDK 安装时有个选项会问你要不要装公共 JRE,可以跳过。因为 JDK 里已经自带了完整 JRE,再装一个纯属冗余,将来更新版本时还可能造成两个 JRE 互相干扰的诡异问题。
装完之后先别急着验证,因为你的系统还不知道 JDK 在哪儿。这也正是下一步要解决的问题。
2.4 环境变量为什么必须配:原理与步骤
环境变量配置是劝退新手的第一大关,其实背后的原理非常简单。你打开命令行输入javac的时候,系统会先去当前文件夹找有没有这个程序,找不到就去PATH环境变量里记录的目录挨个找。PATH 里存着一串路径,相当于一份“寻人启事”列表。
而 JDK 的javac.exe位于安装目录下的bin文件夹里,所以只要把bin目录加进 PATH,系统就能识别javac和java命令了。
通常我们还会额外设置一个JAVA_HOME,这个变量本身不参与命令查找,但很多下游工具是约定俗成读它的,比如 IDE、Maven、Tomcat。它们启动时会问“JDK 在哪儿”,一看到JAVA_HOME就直接去对应路径找,省得用户每次手动配置。
具体操作步骤(Windows 系统演示):
- 右键“此电脑” → 属性 → 高级系统设置 → 环境变量。
- 在“系统变量”区域点击新建,变量名填
JAVA_HOME,变量值填你的 JDK 安装路径,比如D:\Java\jdk-17。 - 在“系统变量”里找到
Path,双击打开,点击“新建”,输入%JAVA_HOME%\bin。 - 点击确定保存,然后重新打开一个命令行窗口(旧窗口不会刷新变量)。
新版的 Windows 用图形界面追加 PATH 很方便,不用手动加一堆分号。注意不是把JAVA_HOME直接加进 PATH,而是把%JAVA_HOME%\bin加进去,这两个是不同的东西,少了\bin照样找不到javac,这一步报错的人特别多。
至于网上教程里常出现的CLASSPATH变量,在新版 JDK 里已经不需要手动配置了,它原本是告诉 JVM 去哪里找用户类文件的,现在 JVM 会自动从当前目录和依赖库加载。看到让你配 CLASSPATH 的老教程,跳过即可。
2.5 安装验证:java 和 javac 的命令行检查
配置完环境变量,打开新的命令行窗口,依次输入两个命令:
java -version javac -version如果都输出了版本号,说明环境搭建成功。看到类似java version "17.0.x"的输出就对了。如果提示“不是内部或外部命令”,回到 2.4 检查 PATH 是否真的把%JAVA_HOME%\bin加进去了,然后确认新开的窗口是不是真的“新开”。
这里有个很容易混淆的点:java有输出、javac没输出。原因是你的系统之前可能装过 JRE 或者别的软件,把老版本的java也写进了 PATH,而且排在你新配置的路径前面。这时候在命令行执行:
where java系统会列出所有能找到的java.exe路径。如果第一条不是你的 JDK 目录,说明路径顺序有问题,去 Path 里把%JAVA_HOME%\bin上移到最前面即可。这个问题在装了全家桶软件(比如某些国产软件自带 JRE)的机器上特别常见,遇到“版本对不上”的怪事,先查这个。
提示:环境变量全部配置好之后,所有的 IDE 也要通过命令行启动才读得到新变量。部分老版本 IDEA 需要重启甚至重启电脑才能识别,不要慌,这不是坏了。
3. Hello World 的完整通关:编译、运行与常见报错
3.1 一个最小 Java 程序的四个组成部分
环境就绪后,第一步是写代码。新建一个记事本,把下面这段代码原样敲进去:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }保存的时候有两个硬性要求。第一,文件名必须叫HelloWorld.java,和public class后面的名字保持一致;第二,编码格式建议选 UTF-8,如果找不到编码选项,至少保证没有中文字符,否则后面编译阶段容易报乱码错误。
这个最小程序由四个部分组成,每个都有讲究:
public class HelloWorld声明了一个公开类。一个.java文件里可以有多个类,但public类的名字必须和文件名一致。public static void main是程序的入口方法。JVM 启动类的时候会寻找签名恰好是public static void main(String[])的方法,少一个修饰符都会导致“找不到主方法”。String[] args是命令行参数数组,暂时用不到,但必须写上。System.out.println是向标准输出打印一行文字的语句。System是 JDK 自带的类,out是其中的静态输出流,println是它的方法。
3.2 javac 与 java:编译和运行是两件事
写完代码,在HelloWorld.java所在的目录打开命令行,先执行编译命令:
javac HelloWorld.java这个命令不会输出任何东西,但目录下会多出一个HelloWorld.class文件,这才是 JVM 真正能识别的东西。.java是源码,给人看的;.class是字节码,给 JVM 看的。
然后再执行运行命令:
java HelloWorld注意,这里是java HelloWorld,不带.class后缀。很多人第一次都在这里翻车,写成java HelloWorld.class,然后看到Error: Could not find or load main class HelloWorld.class。你可以把java命令理解为“请 JVM 去加载这个类”,类名就是类名,不是文件名。
如果你用的是 IDE,这些编译步骤都被工具自动完成了,但理解这个过程依然很重要,因为命令行是你排查一切疑难杂症的最终手段。IDE 报错千奇百怪,归根结底都是编译期和运行期的报错,命令行会把真实原因显示得明明白白。
3.3 字节码与跨平台原理
编译出的.class文件为什么要单独存在?这就要回到开头说的跨平台原理。
假设你在 Windows 上写出了HelloWorld.java,用javac编译成HelloWorld.class。把这个文件原封不动拷贝到一台 Linux 服务器上,只要那台服务器装了 JDK,运行java HelloWorld就能出结果,不需要重新编译。
原因是.class文件里的字节码指令是“全球通用”的,它不针对任何具体 CPU 和操作系统,只等着对应平台的 JVM 来做翻译。Windows 版 JVM 把字节码翻译成 Windows 认识的调用,Linux 版 JVM 翻译成 Linux 认识的调用,同一份字节码,在不同的翻译官手里输出相同的结果。
这个设计在今天看来很平常,但在 Java 诞生的年代,跨平台是杀手级特性。理解字节码还有一个实际用途:将来排查问题时,你可能需要反编译.class文件来看别人的代码逻辑,或者确认某个 jar 包里到底有哪些类,都是围绕这个文件格式展开的。
3.4 第一天最常见的三个报错排查
我整理了一下新手第一天最常遇到的三个报错,以及对应的解决思路:
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
Bad command or file name/'javac' 不是内部或外部命令 | PATH 没配置好 | 回到 2.4 检查环境变量,重新开命令行 |
Error: Could not find or load main class HelloWorld | 类名不对、路径不对或命令带了.class | 确认所在目录有.class文件,运行java HelloWorld不带后缀 |
错误: 编码 GBK 的不可映射字符 | 源码用了 UTF-8,但编译时用了平台默认编码 | 编译命令加-encoding UTF-8,或保存时把文件编码改成 GBK |
第三个报错在中文 Windows 系统上特别常见。如果确认源码没有中文字符却依然报错,检查是不是代码第一行有隐藏的 BOM 头,用记事本“另存为 UTF-8 无 BOM”再存一次就好。命令行的-encoding UTF-8参数是个万能解法,它能强制指定编译器按 UTF-8 读取源码,推荐写进习惯里。
排错时要记得一个原则:报错信息永远是最诚实的。新手最容易犯的错误是看到英文报错就慌,其实每一条报错都在告诉你具体的位置和原因。以后遇到任何看不懂的报错,先整个复制下来,再逐词翻译,90% 的问题都能自己定位。
4. 变量与数据类型:第一天的语法地基
4.1 变量的本质:内存里的盒子
Hello World 跑通之后,就该接触正经的语法了,第一个概念是变量。变量的本质可以理解成一个“贴了标签的盒子”:盒子里放着数据,标签是变量的名字,程序通过标签来读写盒子里的内容。
比如执行int age = 25;这句话,JVM 会在内存里开辟一小块区域,标记为age,这个区域只能放整数类型的数据,并且初始填进 25。之后程序里用到age,就相当于去这个盒子取数据;给age重新赋值,就相当于把盒子里旧东西倒掉换成新的。
这个类比能解释几个常见概念:
- “声明变量”是造一个空盒子并贴标签,比如
int age;。 - “初始化”是第一次往盒子里放东西,
int age = 25;声明加初始化一步到位。 - “变量类型”决定盒子的大小和能放什么东西。
int的盒子不能直接塞一个小数字符串,就像鞋盒装不了大象。
4.2 八大基本数据类型一张表看清
Java 有八种基本数据类型,它们不是对象,直接存值,是组成更复杂类型的基础积木。八种类型按照用途可以分成四组:整数型、浮点型、字符型、布尔型。我把关键参数整理成了一张表:
| 类型 | 占用空间 | 取值范围 | 默认值 | 典型用途 |
|---|---|---|---|---|
byte | 1 字节 | -128 到 127 | 0 | 文件读写、网络传输中的字节流 |
short | 2 字节 | 约 -3.2 万到 3.2 万 | 0 | 很少单独使用 |
int | 4 字节 | 约 -21 亿到 21 亿 | 0 | 最常用的整数类型 |
long | 8 字节 | 约 -9.2 千亿亿到 9.2 千亿亿 | 0L | 时间戳、大数值计算 |
float | 4 字节 | 约 ±3.4E38(7 位有效数字) | 0.0f | 精度要求低的浮点运算 |
double | 8 字节 | 约 ±1.7E308(15 位有效数字) | 0.0d | 默认的浮点类型 |
char | 2 字节 | 0 到 65535 | '\u0000' | 单个字符 |
boolean | 未明确定义 | true / false | false | 逻辑判断 |
这张表值得抄下来贴在电脑边上。初学者最容易记混的是int和long:数字比较大的时候,很多人直接写long x = 123456789012;以为没问题,结果编译报错,因为字面量默认是int类型,超出int范围了。正确写法是在数字末尾加L,写成123456789012L,提醒编译器“这是个 long”。
float同理,不写f后缀时数字默认是double,如果赋给float变量会报“精度丢失”错误。这些细节不是语法刁难,而是为了防止你在不知不觉中丢失数据。
4.3 声明、赋值与字面量:动手写一段完整的代码
光看概念容易飘,我们写一段能运行的代码,把这些语法串起来:
public class DataTypeDemo { public static void main(String[] args) { int age = 25; long timestamp = 1700000000000L; double price = 99.9; char grade = 'A'; boolean isPassed = true; System.out.println("年龄:" + age); System.out.println("时间戳:" + timestamp); System.out.println("价格:" + price); System.out.println("等级:" + grade); System.out.println("是否通过:" + isPassed); } }这段代码里有三个值得注意的细节:
System.out.println("年龄:" + age)里的加号是字符串拼接,Java 遇到字符串和数字相加时,会自动把数字转成字符串再拼在一起,这是新手理解输出语句的关键。char grade = 'A';用的是单引号,字符串才用双引号,单双引号不能混用,char grade = "A";会直接编译报错。boolean isPassed = true;只有true和false两个值,不能写成 1 或 0,这和 C/C++ 的习惯不同。
把这段代码存成DataTypeDemo.java,编译运行一次,你会看到每个变量以字符串形式打印出来。看到输出那一刻,你就明白这四组数据类型的实际用法了。
4.4 类型转换容易踩的坑
类型转换是第一天最容易出隐藏 bug 的点。Java 的类型转换分两种:自动转换和强制转换。
自动转换发生在小类型向大类型赋值时,比如int赋给long、float赋给double,这种转换安全,编译器自动完成,因为大类型的盒子完全装得下小类型的数据,不会被挤爆。
强制转换则相反,比如double赋给int,需要显式写(int)。强制执行时,小数部分会被直接截断,而不是四舍五入。int x = (int) 99.9;得到的结果是 99,不是 100。这个行为让很多人第一次写金额计算时吃了大亏。
还有一个隐蔽的坑是整型除法。执行int a = 5 / 2;,结果不是 2.5,而是 2。因为两个int相除,结果还是int,小数部分被舍弃。如果想让结果为 2.5,必须至少把其中一个操作数转成浮点数:double b = 5.0 / 2;。
这些规则归根结底是一句话:类型转换要刻意为之,不能指望编译器替你兜底。尤其是金额计算,一律用BigDecimal,浮点类型做加减乘除会累积误差,这是 Java 开发者用惨痛教训换来的共识。
4.5 一个能反映综合应用的小例子
把变量、数据类型、字符串拼接和类型转换放在一个小程序里练一遍,效果比背十遍概念都好:
public class CalculatorDemo { public static void main(String[] args) { int price = 199; int count = 3; int total = price * count; double discount = 0.88; double finalPrice = total * discount; System.out.println("原价:" + total + " 元"); System.out.println("折后:" + finalPrice + " 元"); System.out.println("取整:" + (int) finalPrice + " 元"); } }这个例子虽然简单,但涵盖了变量声明、乘法运算、浮点乘法、精度截断和字符串拼接。运行后你可能会发现“折后”那一行输出了一长串小数,比如525.3600000000001——这就是浮点数在二进制里无法精确表示导致的经典现象,也正好为后面介绍BigDecimal埋个钩子。第一次看到别慌,这不是你的代码写错了,是所有使用浮点数的语言都会出现的正常现象。
5. 标识符命名规则:从第一天起写可读的代码
5.1 标识符的硬性规则:四条红线不能碰
前面写的age、price、HelloWorld这些名字,统称为“标识符”。Java 对标识符的合法性有硬性规定,违反了直接编译不通过。四条红线必须记住:
- 只能由字母、数字、下划线(
_)和美元符号($)组成,其他字符一律不行。空格、连字符、星号都非法。 - 不能以数字开头。
1abc非法,abc1合法。 - 不能是关键字或保留字。
class、public、static、void、int这些都已经被 Java 征用了,你不能拿它们当名字。true、false、null也属于特殊值,不能作为标识符。 - 大小写敏感。
age和Age是两个完全不同的名字,Public和public也不是一回事。前者可以当标识符,后者是关键字。
我见过有新手为了绕过规则,把变量名写成class1,这完全没问题,因为class1不是一个单独的关键字。但把变量名写成_也建议别用,因为下划线单独作为标识符在 Java 9 之后被列为未来可能弃用的形式,没有实际好处。
这里还有一个容易误解的细节:汉字可以做标识符。Java 语法允许int 年龄 = 25;这种写法。但从团队协作的角度强烈不建议,原因不是技术层面,而是国际化和项目兼容层面的问题——万一接手项目的人在英文系统下打开你的源码,看到满屏中文变量名,第一反应多半是骂人。
5.2 驼峰命名规范:类名、变量名、方法名/常量各一套
合法性和规范性是两码事。合法的标识符不一定规范,而规范是为了让代码像同一双稳定的手写出来的一样,避免十年后接手的人看你的代码像看天书。Java 社区通用的命名规范是“驼峰命名法”,分两种形态:
- 大驼峰(PascalCase):每个单词首字母大写,用于类名。比如
HelloWorld、OrderService、StudentInfo。类名本质上描述“这个东西是什么”,所以用名词性短语。 - 小驼峰(camelCase):第一个单词全小写,后续单词首字母大写,用于变量名和方法名。比如
totalPrice、getUserName、isPassed。
此外还有两类特殊规则:
- 常量:全部大写,单词之间用下划线分隔,例如
MAX_VALUE、DEFAULT_TIMEOUT。命名常量的核心含义是“这个值在程序运行期间绝对不变”,所以全大写能形成视觉冲击。 - 包名:全部小写,通常使用域名倒写,例如
com.example.project。包名不参与驼峰体系,单独记一种风格。
方法名有点特殊,它通常是动词开头的,因为方法描述“动作”。比如calculateTotal、getUserById。如果你看到的方法名以is或has开头,通常说明它返回一个布尔值,比如isValid、hasPermission,这是 Java 社区约定俗成的阅读习惯。
5.3 为什么第一天就要较真命名
很多人觉得命名规范是洁癖,能跑就行。但我见过太多的真实例子:一个支付项目里,有同学把金额变量命名为a,把折扣命名为b,把最终价格命名为c,自己写完三天后再看就忘了c代表什么,更别说团队其他人了。Debug 的时候还要对着纸笔翻译“a 乘 b 再减 c”,直接崩溃。
第一天就养成好命名的原因有两个。第一,好命名能直接减少 debug 成本。变量名自带注释属性,finalPrice一眼就知道是最终价格,而fp需要你回忆上下文。第二,命名规范会影响别人对你代码的第一印象,在 code review 和面试手写代码环节,一个命名规整的代码片段会给人“这人有工程习惯”的判断。
实际上,很多公司已经把命名规范写进了检查工具里,代码不合规根本提交不上仓库。与其等到那时候被工具逼着改几十处名字,不如从第一个变量就养成习惯。
5.4 一组命名正反例对照,照着改就对了
与其抽象地背规则,不如直接看一组正反例,你可以对比一下差别:
| 场景 | 反例 | 正例 | 原因 |
|---|---|---|---|
| 订单金额 | double a = 100.5; | double orderAmount = 100.5; | 反例无法从名字判断含义 |
| 用户年龄 | int age1 = 25; | int userAge = 25; | 数字编号替代不了语义 |
| 计算总价 | double x = price * count; | double totalPrice = price * count; | x需要额外注释才能理解 |
| 是否通过 | boolean p = true; | boolean isPassed = true; | is前缀暗示布尔类型 |
| 类名 | class helloworld | class HelloWorld | 类名必须大驼峰 |
看完这张表,再回头看你今天写过的变量名,如果里面有a、b、x这种没有语义的,趁现在改成有意义的单词。第一天就能写出“以后自己也看得懂”的代码,比任何技巧都值钱。
最后再分享一个小技巧:Java 编译报错并不可怕,真正可怕的是编译通过却跑出错误结果。所以每写完一小段代码,不要急着写下一段,先运行一遍,确认输出符合预期。我自己的习惯是“写三行跑一次”,这个习惯让我从第一天到现在省下了无数查 bug 的时间。第一节到这里,环境已经跑通,语法地基也打了一层,接下来就是把这份手感和逻辑继续往下延续。