跳到内容

第 1 卷 / 第 1 章 / 第 1 课

1.1 Hello World,你的第一个程序 ​

前置知识:会打开终端并进入一个目录

预计时间:20 分钟

练习环境:JDK 17 或更高版本与 Bash;采用 Java 17 的传统入口写法

完成标志:能独立编译、运行 HelloWorld.java

先让机器回你一句话,再拆开里面的术语。

1. 确认 JDK 可用 ​

在终端运行:

bash
javac --version
java --version

两条命令都应打印版本信息,例如:

text
javac 17.0.x
openjdk 17.0.x ...

具体厂商、补丁号和第二行格式可能不同。这里要确认两件事:

  • javac 存在:它把 .java 源文件编译成 JVM 使用的 .class 字节码文件;
  • java 存在:它启动 Java 虚拟机,加载并执行类。

如果终端提示找不到命令,先按 dev.java 的 JDK 安装指南 安装 JDK,再重新打开终端。只安装用于运行程序的运行环境,未必会提供 javac。编译和运行先使用同一套 JDK;较新的编译器默认生成的字节码,较旧的 JVM 可能无法加载。

2. 建一个干净的练习目录 ​

bash
chapter1_workdir=$(mktemp -d)
readonly chapter1_workdir
mkdir -p "$chapter1_workdir/hello-java"
cd "$chapter1_workdir/hello-java"

用任意纯文本编辑器新建 HelloWorld.java。不要保存成 HelloWorld.java.txt。

java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

文件名中的大小写必须与公开类 HelloWorld 完全一致。

3. 编译 ​

先建立输出目录,再编译:

bash
mkdir -p out
javac -d out HelloWorld.java

成功时,javac 通常不打印任何内容。检查产物:

bash
find out -type f -name '*.class' -print

应能看到:

text
out/HelloWorld.class

源文件和产物分开放置有两个好处:目录更清楚,也不容易误运行以前留下的旧 .class 文件。

4. 运行 ​

bash
java -cp out HelloWorld

预期输出:

text
Hello World!

这里的 -cp out 告诉启动器去 out 目录找类。传给 java 的是类名 HelloWorld,不是文件名,因此不要写成 java -cp out HelloWorld.class。

text
源文件 HelloWorld.java
        │ javac -d out
        ▼
字节码 out/HelloWorld.class
        │ java -cp out HelloWorld
        ▼
JVM 加载并执行,终端出现输出

5. 改完代码要重新编译 ​

把输出改成:

java
System.out.println("Hello from the programming-basics section!");

然后重复:

bash
javac -d out HelloWorld.java
java -cp out HelloWorld

如果只运行第二条命令,JVM 仍会执行上一次编译留下的字节码。源文件的修改不会自动进入 .class 文件。

一个可选捷径 ​

Java 11 起,启动器支持直接运行单个源文件:

bash
java HelloWorld.java

这适合一次性小程序。当前练习仍采用 javac 再 java 的显式流程,因为它能让你看清编译产物,也更接近后续多文件项目的构建过程。两种命令不要混在同一次排错里。

与 Python、C++ 的差别 ​

Python 常见的运行方式没有用户手动执行的独立构建命令:

bash
python3 hello.py

这不等于 Python “完全不编译”。以 CPython 为例,解释器通常会先把源码编译成字节码,再由虚拟机执行;只是这个过程由运行命令代办。

C++ 通常先把源码编译、链接成当前平台使用的本机可执行文件:

bash
g++ hello.cpp -o hello
./hello

Java 的 .class 文件面向兼容的 JVM;C++ 产物通常受操作系统、CPU 架构、ABI 和依赖影响。两种语言都能编写可移植源码,但产物的运行条件不同。

快速排障 ​

现象先检查
javac: command not found是否安装 JDK;新终端的 PATH 是否包含 JDK 的 bin
找不到 HelloWorld.java当前目录是否正确;用 pwd 和 ls 确认
class HelloWorld is public...文件名是否正好是 HelloWorld.java
Could not find or load main class是否编译成功;-cp out 是否指向产物目录;类名是否大小写一致
输出仍是旧文字修改后是否重新运行 javac

收工前 ​

确认两条版本命令可用,out/HelloWorld.class 确实存在,并且修改文字后只有重新编译才会改变输出。然后清理练习目录:

bash
cd
ls -ld -- "$chapter1_workdir"
rm -r -- "$chapter1_workdir"

屏幕上的一句问候并不复杂,但你已经留下了四份可以核对的证据:源文件、编译命令、字节码和运行结果。以后项目会变大,工具会变多,排错时仍要沿着这条链逐段确认。

终端已经回应了你。下一讲把这几行代码逐层拆开。

→ 下一步:逐行理解 Java 代码

参考:Java 17 java 启动器说明、Java 17 javac 编译器说明。

Built with VitePress | Software Systems Atlas