
如果你准备学 Java绝大多数人面对的第一个坎不是语法而是“装环境”。我第一次真正接触 Java 的那天花了大半个晚上在折腾 JDK 和环境变量连 HelloWorld 都没有编译通过半夜差点想把电脑合上。事后回头看Day1 的内容其实特别清晰搞清楚 Java 的运行机制、把环境跑通、写出第一段能运行的代码、试着理解对象和类这两个天天见面的概念。至于面试题、八股文、并发容器和 Lambda 表达式第一天真的不用碰。这篇文章就是把我认为 Java 第一天最该做的事以及最容易踩的坑按真实的学习顺序写一遍。这篇记录不是零基础教学视频的替代品而是一份“过来人”的行动清单。无论你是刚下载 JDK 准备开始还是已经跟着教程写了几行代码但没理解为什么要这样写都可以对照着看。我会重点拆解环境变量配置背后的逻辑、从 HelloWorld 到数组异常之间到底要练什么、面向对象为什么不能靠背、以及几个 Day1 高频报错的真实原因。1. 为什么说 Day1 的胜负手是环境而不是天赋1.1 JDK 选型先分清 JRE、JDK 和 JVM很多新手会在第一步就迷失在名词里JVM、JRE、JDK还有 OpenJDK、Oracle JDK、Temurin、Adoptium。其实 Day1 只需要记住一个粗略的模型Java 源代码先被编译成字节码字节码再由 JVM 解释执行。JVM 是 Java 跨平台的“虚拟机”JRE 是运行 Java 程序所需的最小环境包含了 JVM 和基础类库JDK 则是开发者工具箱既包含 JRE又包含编译器和各种命令行工具。所以安装的时候务必装 JDK而不是只装 JRE。现在最常见的版本是 JDK 17 和 JDK 21两者都是长期支持版本。如果没有任何历史包袱我建议直接选新一点的 LTS 版本比如 JDK 21因为部分开源库和教程开始基于新版本演示。下载渠道推荐 Adoptium Temurin它是目前社区用得很广的 OpenJDK 发行版免费、稳定也没有乱七八糟的捆绑软件。1.2 JAVA_HOME 和 Path 的真实作用配置环境变量时网上教程都会让你新建一个 JAVA_HOME然后把 bin 目录加到 Path 里。为什么要多此一举我见过不少初学者直接把C:\Program Files\Java\jdk-17\bin写进 Path也能跑java -version但后面一旦安装 Maven、Tomcat 这类工具它们会优先找 JAVA_HOME找不到就会报错。可以把 JAVA_HOME 理解成给系统的一个“软连接”。将来你想切换 JDK 版本只需要改 JAVA_HOME 这一个变量Path 里的%JAVA_HOME%\bin不用动。Windows 下面是%JAVA_HOME%\binmacOS 和 Linux 则写成$JAVA_HOME/bin。配置完成后千万记得重新打开终端窗口否则新环境变量不会生效。验证是否配置成功只需执行两条命令java -version javac -version1.3 我第一次配置环境踩过的坑我第一天最蠢的坑是把JAVA_HOME配置成了jdk-17\bin而不是 JDK 根目录。于是java命令能用但javac提示找不到文件。原因是javac就住在 bin 目录里如果 JAVA_HOME 写到了 bin系统会去bin\bin里找编译器自然找不到。另一个常见问题是电脑里已经装了其他 JDK 版本配置了半天java -version显示的还是旧版本。这时候不要急着删文件先执行where javaWindows 会列出所有被找到的 java.exe 路径Linux 或 macOS 用which -a java。查出来之后把 Path 里更靠前的旧版本路径移到后面或者直接清理掉。Day1 能冷静处理这种环境问题后面遇到诡异报错时的心态会好很多。2. 从 HelloWorld 到第一次“崩溃”Day1 的核心代码量2.1 编译运行的本质javac 和 java 各干一件事环境准备好之后不要急着用 IDE 新建项目。我建议先在记事本或 VS Code 里创建一个HelloWorld.java然后在终端里手动编译运行一次。原因很简单IDE 帮你屏蔽了太多细节你不亲眼看到 class 文件出现就很难理解 Java 程序的两段式执行。public class HelloWorld { public static void main(String[] args) { System.out.println(Hello, Java); } }终端里执行javac HelloWorld.java java HelloWorld执行javac后目录下会出现一个HelloWorld.class文件。java HelloWorld不需要带.class后缀因为 JVM 会把类名映射到文件。这里还有一个很多人踩过的坑类名必须和文件名一致HelloWorld.java里不能定义一个叫Hello的 public 类否则编译直接失败。2.2 运算符和表达式Day1 要用代码去验证基础语法里运算符本身不难但有几个细节值得用实际行动确认。比如整数除法int a 7 / 2; System.out.println(a); // 3这行输出是 3不是 3.5。因为两个 int 相除结果还是 int小数部分被丢掉不是四舍五入。同理7 % 2得到余数 1在判断奇偶、循环取值时特别常用。另一个容易搞混的是自增运算的前后位置。i是先使用 i 再自增i是先自增再使用 i。看起来绕写段代码就跑明白了int i 3; System.out.println(i); // 输出3此时i变成4 System.out.println(i); // 输出5因为i先自增成5再输出2.3 数组越界是第一个值得“故意犯一次”的错很多教程把异常放到很后面讲但我觉得 Day1 就应该故意写一次越界代码因为这是你认识异常机制的最好入口。数组的下标从 0 开始长度是 3 的数组合法下标是 0、1、2。一旦访问arr[3]JVM 就会抛ArrayIndexOutOfBoundsException。public class ArrayDemo { public static void main(String[] args) { int[] arr {10, 20, 30}; try { System.out.println(arr[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(捕获到数组越界异常 e.getMessage()); } } }异常机制可以理解成程序里的“安全气囊”。Day1 不需要把异常体系全部学完但要明白看到 Exception 不意味着天塌了它只是告诉你哪一行出了问题学会看堆栈信息比盯着一张报错截图发呆有用得多。2.4 第一次听说 OutOfMemoryError 不要慌热词里有一条java: outofmemoryerror: insufficient memory新手第一次遇到时多半会手足无措。实际上这个错误绝大多数情况不是你的电脑内存不够而是程序在短时间内创建了大量对象或数组把堆内存打满了。比如下面这段代码int[] big new int[1000000000]; // 10亿个int约4GB内存Day1 如果你的代码出现了 OutOfMemoryError不用深入 JVM 参数调优先把代码里的数组大小调小或者检查是不是在循环里不断 new 对象。理解到这个层面应付前两周的学习足够了。3. 面向对象编程不是理论是写出来的习惯3.1 用“生产手机”去理解类和对象“类”和“对象”这两个词让很多人晕。我更愿意用模板和产品来类比类是图纸对象是按图纸造出来的实品。图纸定义了手机有屏幕、电池、拍照功能但图纸本身不能打电话只有 new 出一个具体对象才能调用这些功能。写代码时也是这样class Phone { String brand; double price; void call(String name) { System.out.println(正在拨打 name); } } public class PhoneDemo { public static void main(String[] args) { Phone myPhone new Phone(); myPhone.brand Xiaomi; myPhone.price 2999; myPhone.call(张三); } }这里Phone是类myPhone是对象。每个对象都有自己的brand和price但方法只有一份。这种“属性 行为”的结构就是面向对象最基本的表达。3.2 封装、继承、多态Day1 只需要知道它们是干什么用的很多人一上来就死背三大特性结果越背越乱。Day1 其实不需要写出完美的封装代码但可以用生活案例建立直觉。封装把属性私有化对外提供方法。就好像手机的内部结构被外壳封起来你不需要知道主板怎么焊只要会按开机键就行。在代码里private到getter/setter就是最简单的一层封装。继承子类复用父类的属性和方法。比如Dog和Cat都继承Animal它们就不需要各自重复写eat()方法。继承的关键是找共性不是所有东西都适合继承。多态同一个行为在不同对象上表现不同。Animal a new Dog();调用a.sound()时Dog 里有狗的叫声Cat 里有猫的叫声。运行到哪一行方法取决于实际 new 出来的对象而不是变量声明的类型。3.3 枚举Day1 就值得认识的“限定列表”热词里提到了枚举类型的使用。枚举比常量更安全因为它把取值范围限定住了。比如定义一个方向enum Direction { UP, DOWN, LEFT, RIGHT }使用的时候Direction d Direction.UP; System.out.println(d);如果你硬要给它赋一个不存在的值编译器第一时间就能拦住而不是等程序跑起来才崩。这种“直接把错误挡在编译期”的思路会让后面的代码质量提升很多。4. Day1 只需要“见过面”的高级特性千万别深挖4.1 Lambda 表达式先记住长什么样热词里有 Lambda 函数。Day1 如果看到 Lambda 不必害怕它本质上就是一个简化的匿名函数写法。最常见的一个场景是把一段逻辑传给某个方法。Runnable task () - System.out.println(任务开始); Thread t new Thread(task); t.start();这里的() -就是 Lambda 表达式表示一个没有参数、不返回值的动作。你现在不需要理解Runnable是怎么被实现的只要认得它知道它是 Java 8 之后“行为参数化”的一个重要写法就行。等真正学到函数式接口和 Stream 流的时候再回来看这一行会非常通透。4.2 容器从数组到 ArrayList数组的长度一旦创建就不能变非常不方便。Day1 学完数组后可以顺手了解一下ArrayList因为它是 Java 最常用的容器之一。import java.util.ArrayList; ArrayListString names new ArrayList(); names.add(Alice); names.add(Bob); names.add(Charlie); System.out.println(names.size()); // 3 System.out.println(names.get(0)); // Alice是泛型用来限定集合里放什么类型的元素。Day1 不需要深挖泛型原理但可以记住ArrayList底层是一个自动扩容的数组所以它比普通数组更灵活。当你说“Java 容器”时其中大部分印象都来自ArrayList、HashMap这些类。4.3 排序算法先看思路再决定要不要背面试八股里冒泡排序和快速排序出现频率很高。但 Day1 就硬背代码性价比极低。我建议你先看一遍思路理解下来然后关闭视频自己试试。冒泡排序的思路是每一轮从头到尾比较相邻两个数把大的往后挪像气泡一样浮到末尾。完整代码并不短但最核心的是这段内层逻辑if (arr[j] arr[j 1]) { int temp arr[j]; arr[j] arr[j 1]; arr[j 1] temp; }快速排序的思路是分治选一个基准数把小于它的放左边、大于它的放右边然后对左右两个子区间递归做同样的事情。Day1 你唯一需要记住的是冒泡直观但慢快速排序在生产中更常见。等学到递归和排序章节再回来手写效果比现在死记好得多。4.4 异步并发CompletableFuture 为什么不能现在学热词里还有CompletableFuture。它属于并发编程工具用来编排异步任务。如果你是 Day1 的新手看到“异步”“线程池”这类词很容易产生“我是不是永远学不会”的恐慌。其实完全没必要。CompletableFuture 是建立在多线程、函数式接口、异常处理等一堆基础之上的高阶用法。第一天只需要知道Java 里面还有这样的工具以后一定会遇到但现在不用碰。学习路线本来就是螺旋上升的先把基础打牢后面一天能顶现在三天。5. Day1 常见的报错与工具链问题排查实录5.1 “源发行版 17 需要目标发行版 17”到底在说什么这个警告在热词里出现非常典型。它的意思是源代码文件的编译版本是 17但项目目标运行版本不是 17两者不一致。最常见的场景是你电脑装了 JDK 17但 IDE 里 Project Structure 或者 Maven 配置里悄悄指定了一个低版本比如 8。于是编译器不满“源码是 17 的语法你让我编译成 8 版本的内容我看不懂。”解决方案很简单去 IDE 里把 Project SDK 和 Java 版本全部统一为你安装的 JDK 版本。如果是 Maven 项目检查pom.xml里的maven.compiler.source和maven.compiler.target。这句话背后的教训是版本不一致的问题优先找“编译器看的是哪一个配置”而不是重装 JDK。5.2 Lombok 不生效多半不是安装问题热词里还有一条java: you arent using a compiler supported by lombok, so lombok will not work。这个报错同样让很多人崩溃。Lombok 是一个用注解自动生成 getter、setter、构造方法的小工具它会在编译阶段介入所以 IDE 必须开启“注解处理”功能。如果你把 Lombok 依赖加到项目里代码却报找不到 getter/setter先按这个顺序排查检查 Maven 或 Gradle 是否真的下载了依赖检查 IDE 是否安装了 Lombok 插件检查 IDE 设置里的 Annotation Processing 是否启用。绝大多数情况下都不是 JDK 或 Lombok 本身的锅而是 IDE 没开注解处理。5.3 JD-GUI 反编译好奇心的正确打开方式当你编译出.class文件后如果直接打开会看到一堆乱码因为那是字节码不是给人看的。JD-GUI 是一个反编译工具可以把 class 文件还原成可读的 Java 源码。Day1 如果顺手把上一步的 HelloWorld.class 拖进 JD-GUI看到几乎一模一样的源代码会有一种“原来字节码还能被还原”的直观感受。但我要提醒一句不要养成依赖反编译来学知识的习惯。很多闭源库只有编译后的 class你可以看反编译结果但无法看到完整的注释和真实开发意图。Day1 用 JD-GUI 好奇一下就够了真正动手写代码才是正道。6. Day1 之后的学习路线与面试题心态6.1 从 Day1 到 Day30节奏大致是这样很多人不知道自己应该按什么顺序学。我给一个建议路线Day1 到 Day3 搞定环境、基础语法、运算符和流程控制Day4 到 Day7 搞定数组、方法、面向对象和常用类第二周开始学异常、集合、泛型和 IO第三周学多线程、网络编程和 JDBC第四周开始做一个小项目收尾比如记账本或者学生管理系统。这个节奏不激进每天保证三四个小时有效输入三十天之后你至少能独立写一个带界面的小程序。6.2 面试题和“八股文”什么时候看不吃亏热词里“java面试题”“java八股文”非常火很多新手 Day1 就想开始背这其实是本末倒置。面试题的存在是为了筛选是对基础的“提炼”而不是学习顺序。如果你连类加载、HashMap 底层都没见过背出来的答案也只是空中楼阁面试官深挖两句就露馅。我建议至少完成第一个项目之后再去看面试题。那时候每道题都能对应到你写过的某个功能点背起来也会很快。6.3 我的三条 Day1 建议第一输出优先。今天学的语法今晚必须用代码写一遍哪怕只是照着抄也要亲手敲一遍。第二遇到异常先读英文。JVM 的报错信息已经是所有开发工具里比较清楚的了不要一看到英文就想复制去翻译软件。第三先跑通再优化。Day1 的目标是让程序运行起来不是写出一段完美无缺的代码。你写的代码再笨、再啰嗦只要它能跑就比“精心构思但没运行”强一百倍。Day1 的内容看起来多其实核心只有三个环境跑通、基础语法理解、面向对象有感觉。如果你今天刚好是 Day1别急着和别人的进度比。我见过太多人在第一天就选择放弃原因不是 Java 难而是被环境变量和报错信息磨掉了耐心。可这些坑每一个走过来的人都会踩。把每一次报错当成一次排查练习很快就发现所谓“会 Java”无非是见过的报错比新手多了一点而已。