
前阵子帮一个刚转行的朋友排错他把书里的 Hello World 原封不动敲进记事本存成Hello.java双击以后发现啥反应都没有跑来问我“代码不是照着写了吗怎么程序不运行”。这个场景我见过太多次很多新手第一次接触 Java 就卡在这——不是代码不会抄而是根本不知道“写代码”和“让代码跑起来”之间还隔着一道工序。这篇文章不绕弯子直接从 Hello World 这条最简单的程序出发把 IDEA 图形化操作和命令行手工编译两条路都走一遍顺便把 Java 从源码到运行的全部过程拆开看个明白。内容适合两种人一种是刚装完 JDK、准备敲第一个 Java 程序的零基础读者另一种是早就会用 IDE 点运行、但始终不太清楚背后编译和 JVM 到底干了什么的同学。看完以后你不仅能复现整个流程以后遇到“找不到主类”“中文乱码”这类经典报错也能自己判断问题出在哪。1. 学Java第一步为什么绕不开Hello World1.1 Hello World真的是“最简程序”吗所有编程语言的入门都是从 Hello World 开始的Java 也不例外。先看这一段最标准的 Java 代码也是全文反复会用到的主线public class HelloWorld { public static void main(String[] args) { System.out.println(Hello, World!); } }我经常跟新手说这段代码看起来简单但它其实一点都不“简单”。你数一数它已经覆盖了多少 Java 的核心语法元素public是访问修饰符表示这个类或者方法对外可见class是定义类的关键字Java 里万物皆对象一切代码都要写在类里面HelloWorld是类名命名要符合标识符规则首字母大写的驼峰形式是行业习惯static表示静态成员不需要 new 对象就能被调用void表示方法没有返回值main是固定的方法名JVM 启动程序时默认找它作为入口String[] args是命令行参数的载体后面运行程序时传给程序的额外数据都会以字符串数组的形式装在这里System.out.println是往标准输出打一行文字的调用语句括号里的字符串就是要打印的内容最后是分号结尾、大括号配对这些是最容易被忽略却又最容易出错的语法细节。一个只学了十分钟的人照着敲可能也能敲出来但能不能讲清楚里面每一处的设计原因就是另外一回事了。正因为这段代码浓缩了“类、方法、输出语句、修饰符、参数”等等基本面它才配得上“入门第一课”的位置。它是整个 Java 知识体系的最小微缩模型。1.2 会写代码不等于会运行代码回到我朋友的那个困惑。他把代码写进了记事本文件的扩展名是.txt就算把内容复制成Hello.java他双击这个文件也不会弹出任何程序窗口。原因很简单扩展名是.txt的记事本文件在 Windows 上默认被关联到文本编辑器系统根本没有“执行一段 Java 代码”的能力。Java 程序的运行不是双击文件就能触发的后面必须跟上“编译”和“运行”两步动作。很多人第一次接触 IDE集成开发环境之后被图形界面“惯”坏了以为学编程就是打开 IDEA 点一下绿色三角形看控制台输出就完事。这样学表面上很顺利一旦脱离 IDE 环境就会手足无措。这就像学开车自动挡开得再顺手也得知道发动机是怎么启动的、刹车失灵意味着什么。IDE 把编译和运行的细节全部藏了起来你不主动去了解就永远只停留在“知道怎么点按钮”而不是“搞懂是怎么回事”这个层次。1.3 两条路线一个核心原理这篇文章里我会带你走两条路第一条路是在 IDEA 里完成图形化操作这对日常开发效率最高第二条路是打开终端用javac和java这两个命令手工编译、运行这对理解原理最有用。两条路殊途同归最终都会落在一个核心原理上——Java 源码必须经过编译变成字节码然后由 JVM 解释执行。接下来的内容就是围绕这个原理一层层扒开来看。2. 装好JDK之前先搞懂工具链里每个角色的分工2.1 JVM、JRE、JDK别再傻傻分不清去网上搜索 Java 安装教程你会发现满屏都是 JDK、JRE、JVM 三个缩写来回混着讲初学者很容易被绕晕。我先把这三者的关系用一句话理顺JVM 是虚拟机负责运行 Java 字节码JRE 是运行时环境等于 JVM 加上 Java 核心类库JDK 是开发工具包等于 JRE 加上开发调试工具。三者的关系是层层包含的JDK 最大包含全部JRE 是中间层JVM 是最内层的运行引擎。我用一个生活化的类比帮你记住。把一台计算机比作一个厨房JVM 相当于“灶台和锅”它只负责把食材字节码烹饪成熟菜程序运行结果但它本身不包含任何食材JRE 相当于“灶台加冰箱”里面除了灶台还储备了做菜需要的各种食材Java 标准类库比如System、String这些现成类JDK 相当于“整套厨房”除了灶台、冰箱还配齐了切菜刀、砧板、调料架这些烹饪工具javac编译器、jar打包工具、javadoc文档工具以及使用说明书文档。如果你只是运行别人编译好的 Java 程序只需要 JRE 就够了但你要自己写代码、把.java编译成.class就必须要 JDK。新手直接装 JDK 就行它自带了 JRE不需要另外装。2.2 JDK版本到底怎么选现在市面上的 JDK 版本多到让人眼花Java 8、11、17、21还有各种发行版。作为一个初学者我的建议很简单选最新的 LTS长期支持版本就行。所谓 LTS就是官方承诺会在很长时间内持续提供更新和安全补丁的版本适合在生产环境长期使用。目前主流的 LTS 版本是 Java 17 和 Java 21选这两个里的任意一个都没问题不用去追最新版本也不要从 Java 8 开始那对新项目来说太老了。至于下载哪个发行版推荐两个常见选择一是 Oracle JDK去 Oracle 官网下载家用和学习免费二是 Adoptium Temurin这是社区主导的开源版本很多大公司都在用同样完全免费。新手不用太纠结选哪个两者从学习角度没什么区别。装的时候注意路径里不要出现中文和空格比如C:\Program Files\Java\jdk-21这样是比较稳妥的位置。这里还要提醒一下不要为了省事去搜索什么“破解版”“绿色版 JDK”这些资源里面有没有被植入恶意代码你根本不知道为一个入门教程搭进去环境安全非常不值得。官方下载本来就不要钱没必要冒这个险。2.3 环境变量到底在配什么JAVA_HOME和Path安装完 JDK还有一道经典工序配置环境变量。很多教程会直接让你在系统变量里新建JAVA_HOME然后在Path里面加一行%JAVA_HOME%\bin。问题是这么配到底是在配什么先说结论配置环境变量的目的是让操作系统能在任意目录下找到java和javac这两个可执行命令。你打开命令提示符输入javac系统会在当前目录找这个程序找不到就去Path环境变量列出的所有路径里依次找。安装 JDK 时已经默认把一些路径写进Path了但很多时候不够明确或者用户自己改动了目录所以手工配置更保险。JAVA_HOME这个变量的作用是给其他依赖 JDK 的工具最典型的就是后面要讲的 IDEA以及 Spring Boot 项目里常用的 Maven、Gradle提供定位 JDK 安装路径的“锚点”。以后你想换 JDK 版本只需要修改JAVA_HOME的值不用去改一堆工具里写死的路径非常方便。具体配置步骤不同系统不大一样Windows 10/11按 Win 键搜索“环境变量”——编辑系统环境变量——环境变量——系统变量里点击“新建”变量名填JAVA_HOME变量值填你的 JDK 安装绝对路径比如C:\Program Files\Java\jdk-21。然后在“系统变量”里找到Path双击它新建一条%JAVA_HOME%\bin保存后新开的命令提示符窗口才会生效。macOS / Linux通常在/etc/profile或~/.zshrc里加入export JAVA_HOME/path/to/jdk和export PATH$JAVA_HOME/bin:$PATH然后执行source ~/.zshrc让配置生效。2.4 安装完成后必须做的验证配置完环境变量第一件事不是急着打开 IDEA而是先打开命令行验证一下。Windows 按Win R输入cmd回车然后依次执行两条命令java -version javac -version正常情况下你会看到类似下面的输出java version 21.0.1 2023-10-17 LTS Java(TM) SE Runtime Environment (build 21.0.112-29) Java HotSpot(TM) 64-Bit Server VM (build 21.0.112-29, mixed mode, sharing)和javac 21.0.1java -version能显示版本说明 JVM 能正常工作javac -version能显示版本说明开发工具已经就位。如果javac那一步提示“不是内部或外部命令”说明环境变量没配对回到 2.3 一步步再检查。这两条命令跑通了你的电脑才算真正具备了开发 Java 的能力。3. 在IDEA里跑通第一个程序从新建项目到点击运行3.1 社区版还是旗舰版新手的正确选择环境搭好以后下一步就是装 IDE。JetBrains 出品的 IntelliJ IDEA 是目前写 Java 用得最多的工具分为旗舰版Ultimate和社区版Community两个版本。很多新手一搜教程看到的经常是旗舰版的破解教程这里必须明确告诉你完全没有必要用破解版社区版对学习 Java 来说功能完全够用而且永久免费、合法安全。旗舰版多出来的主要是企业级框架支持比如 Spring、JavaEE 等等你学到那个阶段再考虑也不迟。下载地址就去 IDEA 官网拉到页面底部找到 Community Edition 的下载入口选择对应自己系统的安装包。安装过程基本一路 Next注意勾选“Create Desktop Shortcut”方便以后启动。装完之后先不用管它打开软件继续。3.2 创建项目的五步操作IDEA 首次启动会让你选择主题配色这个看个人爱好选完以后进入主界面。下面是我推荐给新手的一套最简创建流程在主界面点击 “New Project”如果弹出了项目向导左侧选 “New Project”注意不是 Empty Project在右侧的 “Language” 下拉框里确认选的是 Java“Build System” 选 “IntelliJ”IDEA 版本够新的话可能还会让你选 SDK如果这里下拉框是空的就点 “Add SDK” 选择 JDK 的安装目录填写项目名称比如HelloWorldDemo同时注意一下项目存储路径不要放在中文或带空格的目录下下面有个 “Generate code with sample” 或类似选项新手可以勾上也可以不勾问题不大点击 “Create” 或 “Finish”项目就建好了。这里最容易让新手卡住的地方是把 “New Project” 和 “Empty Project” 搞混。选 “Empty Project” 会生成一个空壳工程你还得自己手动创建模块才能看到源码目录对新手来说多一步解释成本。我们直接选 “New Project” 就好它会自动生成标准的src目录结构。id 里左侧的 “Project” 面板会看到项目文件树展开src或者项目内部的结构就能开始创建你的第一个 Java 类了。如果勾选了示例代码IDEA 会自动生成一个带main方法的 Main 类不必删掉直接在它旁边新建自己的类即可。3.3 写代码和运行绿色三角背后的故事在src目录上右键选择 “New” —— “Java Class”弹窗里输入类名HelloWorld类型选 Class敲回车。IDEA 会自动帮你生成如下的类壳public class HelloWorld { }接下来一句句补全方法体public class HelloWorld { public static void main(String[] args) { System.out.println(Hello, World!); } }写完之后IDE 的编辑区域旁边会出现一个绿色三角按钮点击它或者右键选择 “Run HelloWorld.main()”IDEA 底部会自动打开 Run 面板几秒钟内你就能看到输出C:\Program Files\Java\jdk-21\bin\java.exe ... Hello, World! Process finished with exit code 0看到Hello, World!出现在屏幕上恭喜你已经在 IDEA 里成功运行了第一个 Java 程序。但故事到这里还远没结束我们要问问下面这个问题才能真正把这一章讲透。3.4 点击Run时IDEA在后台做了什么回想一下上一步你只点了“运行”IDEA 从创建到弹出结果都没有让你手动写过一条编译命令。很多人会因此下意识以为“Java 程序不需要编译”这是大错特错。IDEA 之所以能做到“点一下就跑”是因为它在后台替你执行了两条命令你可以从 Run 面板最上方的输出里看到类似这样的痕迹——最开头那一行就是一条长长的java.exe命令说明它实际是启动了一个 Java 进程。在更早的 Build 阶段IDEA 内部还会调用javac把你写的.java文件编译成.class字节码文件然后才把.class交给 JVM 执行。为了证明这一点打开项目目录下的out文件夹IDEA 默认的输出目录等同于 IDE 版的“编译产物目录”你会看到里面躺着一个HelloWorld.class文件。这个文件就是编译后的字节码是 JVM 真正能读懂和执行的东西。javac这个编译动作IDEA 已经悄无声息地帮你做完了。从这个角度看IDE 就像一个自动化程度极高的厨房你只需要把菜谱源代码放上操作台它自动帮你洗菜、切菜、开火、炒菜。方便是方便但不能因此就不知道菜是怎么做出来的。后面第四章和第五章就是带你亲自去看清楚这道“烹饪”流程。3.5 顺手把编码设置改掉避免第一课就乱码在正式写 Java 之前有一件很小但特别影响体验的事就是设置项目编码。如果你的电脑是中文系统且没有经过任何设置IDEA 默认可能在控制台输出时出现中文乱码。这跟 Windows 中文版默认使用 GBK 编码有关而 Java 源码标准推荐使用 UTF-8 编码两边不一致就会出乱码。推荐做法在 IDEA 里按Ctrl Alt S打开设置搜索 “File Encodings”把 Global Encoding、Project Encoding 和 Properties Files 三处都设置成 UTF-8。同时如果你的程序 println 里包含中文保证源文件被 IDEA 以 UTF-8 保存。这一步做完绝大多数中文输出乱码问题都能在 IDE 层面解决。设置好之后再把 Hello World 里要打印的字符串改成中文试试比如System.out.println(你好世界);运行一下正常情况下你会看到控制台输出“你好世界”。如果还是乱码问题大概率出在 IDE 虚拟机的文件编码参数上可以在 Help —— Edit Custom VM Options 里加一行-Dfile.encodingUTF-8重启 IDEA 即可。这一行参数的原理就是让运行在 JVM 里的 IDEA 本身默认使用 UTF-8 解码文件。4. Hello World背后的字节码旅程javac、JVM与class文件4.1 从.java到.class编译器究竟在做什么Java 程序的运行不像编译型语言比如 C/C那样直接生成机器码也不像纯解释型语言比如老版本 Python那样直接逐行解释源码。Java 采用的是“中间产物 虚拟机执行”的路子。你写好的HelloWorld.java是给人看的源码机器看不懂javac编译器把它翻译成一种结构化的、面向 JVM 的中间语言文件也就是HelloWorld.class这个.class文件里装的是字节码bytecode。字节码不是机器指令它是一套专门为 JVM 设计的指令集类似一个“虚拟 CPU”的汇编码。JVM 运行时会逐一读取这些字节码指令翻译成当前操作系统和 CPU 能执行的机器指令程序才能真正跑起来。这一步有点像一个懂中文的人先把英文技术文档翻译成“中文笔记”再让另一个不懂英文但懂中文的工程师按照笔记去施工。.java就是英文原文.class就是中文笔记JVM 就是那位工程师。4.2 字节码为什么能“一次编写处处运行”这个问题几乎是每次 Java 面试都跑不掉的基础题。C 语言在不同平台上编译会各自生成针对 Windows、Linux、macOS 不同的可执行文件而 Java 的javac只需要生成一种通用的.class字节码任何安装了 JVM 的平台都能运行。跨平台的功劳并不在 Java 语言本身而在 JVM 这一层“翻译官”。你在 Windows 上编译出来的HelloWorld.class直接复制到一台装了 Linux 版 JVM 的服务器上放到相同目录结构下用java HelloWorld命令运行照样能打印出Hello, World!。底层的系统调用差异全部由 JVM 屏蔽掉了。这也是 Java 在服务端领域深耕多年的核心原因之一——企业部署环境五花八门Java 程序却能做到“打一个包到处跑”。4.3 JVM拿到class文件后的三步加载、校验、执行字节码文件只是产品真正让它“活过来”的是 JVM。JVM 拿到HelloWorld.class之后主要干三件事类加载类加载器ClassLoader根据你传入的类名在classpath指定的路径里找到.class文件把类的结构信息方法、字段、常量池等加载进内存。你运行java HelloWorld时JVM 就主动去找HelloWorld.class找不到就抛ClassNotFoundException或“找不到或无法加载主类”的报错。字节码校验加载进来的字节码会经过一道安全检查确保没有非法操作比如方法调用的参数个数对不对、类型能不能对上。这一层是为了防止字节码在生成或传输过程中被篡改。解释执行/即时编译校验通过后JVM 开始逐条解释执行字节码指令。对于热点代码还会触发 JIT即时编译把它们编译成当前平台的机器码缓存起来从而大幅提升运行性能。这就是为什么同一个.class文件跑得多了会越来越快的原因。main方法在这里有个特殊地位JVM 从类的方法表中找到签名是public static void main(String[])的方法把它作为线程入口开始执行。一旦这个入口不存在JVM 就直接退出并报错“主方法未找到”。4.4 逐行拆解Hello World的语法为什么main必须public static void很多初学 Java 的人第一次看到public static void main(String[] args)都会一脸问号这行英文比要打印的Hello, World!难懂得多。为什么要这样写每部分能不能变我逐个解释publicJVM 启动时要调用这个方法而调用者JVM不在类所在包内必须声明为 public 才能被外部访问。把它改成 private程序就会在运行时报错找不到 main 方法。staticJVM 在启动程序时并不需要先创建你这个类的对象它希望直接通过“类名.方法名”的方式来调用入口方法。如果不加 static就必须先 new 一个对象才有资格调用但 JVM 的启动逻辑为了防止歧义就是规定了入口方法必须是静态的。voidJVM 启动入口方法后程序接着往下走入口方法是否需要返回一个状态码让操作系统接收Java 的设计答案是“不需要”所以返回值必须是 void。如果你尝试返回intJVM 也会忽略它。main这是约定好的名称类似于“约定大于配置”。JVM 就找这个名字换个写法比如maing运行时照样报错。String[] args这是留给命令行的参数通道。运行java HelloWorld a b c时IDEA 的 “Program arguments” 一栏填的内容会作为字符串数组传给这个参数后面我们可以拿它做各种操作。Java 里还有一个非常严格的规则一个公开类的类名必须与文件名完全一致包括大小写。原因是编译器需要根据类名确定输出.class的文件名JVM 又通过类名去找文件。如果你把文件命名为helloworld.java但类名写的是HelloWorldjavac 会直接报错要求你把类名放进同名文件里。这个规则没有任何灵活性可言必须遵守。5. 回到命令行手工编译一次才算真正懂“编译运行”5.1 你迟早要面对命令行的三个场景很多新手会问既然 IDEA 这么好用为什么还要学命令行这种“古董”操作答案很简单以后你一定会遇到用不了 IDEA 的场合。常见场景至少有三个。面试现场不少公司面试让你现场写代码考官不会给你配好 IDEA往往要求你确认环境后直接编译运行命令行是唯一选择。远程服务器部署线上环境几乎都是 Linux 服务器没有图形界面程序部署、日志查看、进程管理全靠终端命令行完成。你要是连javac和java命令都不会敲连最简单的“手动运行一次程序”都做不到。构建工具绕过即使你用 Maven 或 Gradle 这类自动化构建工具它的底层仍然是指定 JDK 的编译器并调用java来运行测试。理解命令行之后遇到构建工具的报错信息你才能判断问题出在编译阶段还是运行阶段。所以这个“返璞归真”的章节对每一个想深入技术的人都是必修课。5.2 手把手用命令行编译运行HelloWorld首先用一个最简单的纯文本编辑器记事本、VS Code 都可以创建文件HelloWorld.java把下面的代码原样粘贴进去public class HelloWorld { public static void main(String[] args) { System.out.println(Hello, World!); } }保存后打开命令行切换到源码所在目录cd /d 你的源码目录路径比如cd /d D:\JavaProjects\hello然后执行编译命令javac HelloWorld.java这条命令默认不会打印任何信息只是在当前目录生成了一个HelloWorld.class文件相当安静。你可以用lsmacOS/Linux或者dirWindows查看是不是有这个名字出现。有就说明编译成功了。接下来运行程序java HelloWorld注意这里有个无数新手会踩的坑java后面跟的是“类名”不是“文件名”所以千万别写成java HelloWorld.class或java HelloWorld.java。正确的运行命令里没有.class后缀。运行成功的话屏幕会打印Hello, World!这个流程把前面说的所有概念串起来了javac HelloWorld.java完成了“源码 → 字节码”java HelloWorld完成了“类加载 → JVM 运行”。整个过程里没有 IDE 替你干活每一步都清清楚楚。5.3 用javap偷看一眼字节码光知道.class文件里面“有字节码”还不够我建议你打开它看一眼建立直观印象。JDK 自带一个反汇编工具javap执行javap -c HelloWorld你会看到类似这样的输出版本不同格式会略有差异Compiled from HelloWorld.java public class HelloWorld { public HelloWorld(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object.init:()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #13 // String Hello, World! 5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return }看不懂没关系我只想让你注意到两点第一Hello, World!这个字符串明文就在字节码里说明编译并没有把它“加密”第二main方法在字节码层的核心指令只有getstatic获取 System.out 对象、ldc加载常量字符串、invokevirtual调用 println 方法、return返回四条Java 源码和底层指令的对应关系一目了然。以后你在 Java 面试里遇到“说说一个 Java 文件的执行过程”这种问题能从源码讲到字节码、再讲到 JVM 解释执行就已经超过绝大多数面试者了。5.4 一个练习建议把程序改成能接收参数命令行学完以后别急着关窗口做一个五分钟的小练习能让你的理解更上一层楼。把 HelloWorld.java 改成下面的样子public class HelloWorld { public static void main(String[] args) { System.out.println(Hello, args[0] !); } }重新编译运行javac HelloWorld.java java HelloWorld Java这次输出会变成Hello, Java!这里的args[0]就是命令行里传入的第一个参数Java。这个练习让你直观体验到String[] args到底在接收什么。试试多传几个参数在代码里用 for 循环把它们全部打印出来效果更清楚。6. 新手必经的五个坑环境变量、主类加载和中文乱码排查6.1 “找不到或无法加载主类”的完整排查路径这是命令行运行阶段出现频率最高的报错。完整的错误提示类似错误: 找不到或无法加载主类 HelloWorld看到这个报错不要慌按下面的顺序排查百分之八十的情况都能解决检查类名拼写java后面的类名是否和public class声明完全一致包括大小写比如源文件里写的是public class HelloWorld运行命令就必须是java HelloWorld不能写成java helloworld。检查当前目录下有没有 .class 文件先执行ls HelloWorld.class或dir HelloWorld.class没有的话说明还没编译老老实实先把javac那一步跑通。检查是否误加后缀java HelloWorld.class是错的去掉.class再试。检查类是否在包中如果你的源码第一行有package com.demo;那么编译后的HelloWorld.class必须在com/demo目录结构下运行命令必须使用完整类名java com.demo.HelloWorld并且必须在com目录的上一级目录执行。6.2 javac不是内部或外部命令的根因Windows 上刚配完环境变量很容易踩这个坑。报错内容通常是javac 不是内部或外部命令也不是可运行的程序或批处理文件。先说结论这几乎 100% 是环境变量没生效。常见原因有三个Path 没加进%JAVA_HOME%\bin回到 2.3 检查系统变量里的 Path 是否包含这一条。注意不要写到用户变量的 Path 里去给系统所有用户造成混乱直接改系统变量更保险。配置后没有重新打开命令行环境变量只在命令行启动时读取一次你配置它之前就开着的 cmd 窗口不会自动加载新值。重新打开一个新的 cmd 窗口再试。JAVA_HOME 的值写错了变量值必须精确指向 JDK 安装目录这个目录下应该直接就有 bin 子目录。有些人配置成了C:\Program Files\Java\jdk-21\bin导致最终的路径变成C:\Program Files\Java\jdk-21\bin\bin必然找不到。这里分享一个万能的验证方法在命令行执行echo %JAVA_HOME%Windows或echo $JAVA_HOMELinux/macOS看看输出是不是预期路径不是就说明配置没生效按上面三点重新检查。6.3 中文乱码编码问题的三个层面中文乱码问题不仅在 IDE 里会出现命令行更容易遇到而且原因往往藏在三个不同层面上源文件编码你的HelloWorld.java文件本身是用什么编码保存的记事本默认可能是 ANSI推荐统一改成 UTF-8。VS Code 可以在右下角切换编码记事本默认会保存为 ANSI这个要注意。编译编码javac编译时默认使用操作系统平台的字符集。在中文 Windows 上系统默认字符集往往是 GBK如果你的源码是 UTF-8 编码javac就会把 UTF-8 的中文字节按 GBK 解码导致乱码甚至报错。解决办法是显式指定编译编码javac -encoding UTF-8 HelloWorld.java运行控制台编码Windows 的 cmd 默认代码页经常是 GBK代码页 936如果你编译和运行时 JVM 输出的是 UTF-8 字节控制台按 GBK 解码自然乱码。可以在命令行先执行chcp 65001把代码页切到 UTF-8再运行 Java 程序或者在程序里用System.out输出前统一处理但对新手来说更简单的方法是保证源文件、编译编码、控制台代码页三者一致。判断乱码源头有一个技巧看报错信息和正常英文是否清晰。如果是中文乱码而英文正常那基本就是源文件/编译编码问题如果整个输出都是方格或问号可能是字体或控制台代码页问题。6.4 类名和文件名大小写不一致的诡异报错大小写是新手最容易忽略的坑。Windows 的文件系统默认不区分文件名大小写你保存一个helloworld.java文件即使里面类名是HelloWorldjavac 也会因为文件名与类名对不上而报错错误: 类 HelloWorld 是公共的应在名为 HelloWorld.java 的文件中声明解决方式是保持类名和文件名严格一致。更值得警惕的是另一类问题Windows 不区分大小写不代表 Java 运行时不区分。比如你编译时生成了HelloWorld.class之后手动把文件改名为helloworld.class运行java HelloWorld就会找不到类因为 JVM 严格按大小写去搜索。所以建议从最初创建文件时就统一成首字母大写的驼峰风格避免这种隐晦的盘根错节问题。6.5 classpath藏在ClassNotFoundException后面的概念运行 Java 程序时JVM 需要一个路径列表来查找.class文件这个列表就是 classpath类路径。默认情况下JVM 会把当前目录.作为 classpath 的一部分所以你在源码目录直接运行java HelloWorld能成功。如果你的项目文件夹结构一变比如类文件被移动到了其他目录立刻就会出现ClassNotFoundException或前面提到的“找不到或无法加载主类”。命令行里可以用-cp参数显式指定类路径比如java -cp . com.demo.HelloWorld这里的.代表当前目录com.demo.HelloWorld是带包名的完整类名。理解了 classpath以后你用 Maven 管理项目时看到依赖路径配置就不觉得神秘了——它本质上就是在给 JVM 传递一份“去哪里找类”的地址清单。6.6 一份快速自查表新手阶段报错看多了容易眼花我把自己踩坑历史上最高频的几个问题整理成了表格可以直接当备忘录用报错或现象根本原因快速解决办法javac 不是内部或外部命令环境变量未配置或未生效检查JAVA_HOME和Path重开命令行错误: 找不到或无法加载主类类名拼写错误、未编译、带了后缀、包路径错误按 6.1 的顺序排查类 HelloWorld 是公共的应在名为 HelloWorld.java 的文件中声明文件名和类名不一致统一文件名与类名大小写也对齐中文输出乱码源文件编码、编译编码、控制台代码页不一致统一为 UTF-8或javac -encoding UTF-8配合chcp 65001ClassNotFoundExceptionclasspath 没覆盖目标.class文件用-cp指定类路径或在正确目录运行我见过不少人在这个阶段花大量时间收藏教程、买书却连命令行编译都没亲手跑通一次遇到报错就慌。其实不少问题都不用记多踩几次自然就熟了。如果你今天按这篇文章走通了 IDEA 和命令行两条路径往后学循环、数组、面向对象都得心应手得多因为你对“Java 程序本质是一段从源码到字节码再到 JVM 执行的旅程”已经有了完整的画面。最后分享一个个人偏好我教新人的时候不管目标是不是后端开发都要求他们先在命令行把 Hello World 跑通三遍然后才允许打开 IDEA。这样做不是因为命令行更“高级”而是它逼着你把环境、源码、编译、运行四个环节分开理解。等你习惯了这种动手拆解的感觉会发现编程世界里大多数所谓“难题”拆开以后也就那么回事。