零基础起步

零基础起步:把第一个 Java 程序跑起来

假设你什么都没写过。6 个关卡,每一步都告诉你「做什么 / 敲什么 / 你应该看到 / 报错怎么办」。全程约 40 分钟。

6 个关卡19 个微步骤14 条报错速查JDK 8+

走完这 6 关,你就能

  • 能用 javac 编译、java 运行一个类
  • 能声明变量、做类型转换、用 printf 格式化输出
  • 能写 if-else、for、while,会用数组
  • 能定义类、写构造方法、创建对象并调用方法
  • 能用 ArrayList 与 HashMap 存数据
  • 能用 BufferedReader/Writer 读写文本文件
怎么用① 打开命令行或 IDE,页面上说敲什么就敲什么;② 每步都有“你应该看到”,对不上先看“如果报错”;③ 别跳关,第 1 关的程序跑不通,后面都做不了。

第 0 关 · 装 JDK、验证环境(5 分钟)

目标Java 程序的运行靠 JDK:javac 负责编译,java 负责运行。先确认这两个命令能用。
前提:已安装 JDK(没有的话先装 JDK 8 或以上,一路下一步即可)

1① 验证 Java 环境

🎯 打开命令行(Windows 按 Win+R 输入 cmd),执行:

JAVA
java -version
javac -version
👀 你应该看到
java version "1.8.0_301"
Java(TM) SE Runtime Environment (build 1.8.0_301-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.301-b09, mixed mode)
javac 1.8.0_301

两条命令都能输出版本号,说明 JDK 装好了、环境变量也对。

⚠️ 如果报错
  • 'javac' 不是内部或外部命令
    → 只装了 JRE 没装 JDK,或环境变量没配:把 JDK 的 bin 目录加进 PATH。
  • 'java' 不是内部或外部命令
    → JAVA_HOME 与 PATH 都没配好,重装 JDK 并勾选设置环境变量。

2② 认识 JDK / JRE / JVM

🎯 三者的关系是面试常问、也是理解“为什么 Java 能跨平台”的关键:

JAVA
JDK ⊃ JRE ⊃ JVM
JDK = 开发工具(javac、jar)+ JRE
JRE = JVM + 核心类库
JVM = 执行 .class 字节码的虚拟机
👀 你应该看到
(这是一张关系说明,不需要执行)

开发装 JDK,只运行装 JRE;跨平台靠的是“字节码 + 各平台的 JVM”。

3③ 建一个练习目录

🎯 后面所有代码都放这个目录,路径别带中文和空格(避免各种奇怪问题)。

JAVA
mkdir D:\java\demo
cd D:\java\demo
👀 你应该看到
(命令行提示符变成 D:\java\demo>)

路径里的反斜杠是 Windows 写法;Linux/Mac 用 /home/yourname/demo。

✅ 过关标准两条版本命令都能用,就过关。

第 1 关 · 第一个程序:编译与运行(8 分钟)

目标把“写代码 → 编译 → 运行”这条链路亲手走通一次,后面一切都基于它。
前提:JDK 可用(第 0 关)

1① 写 HelloWorld.java

🎯 新建文件 HelloWorld.java(注意大小写,文件名必须和类名完全一致)。

JAVA
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}
👀 你应该看到
(保存文件,目录下出现 HelloWorld.java)

main 是程序入口,格式固定:public static void main(String[] args)。

2② 编译成字节码

🎯 javac 把 .java 编译成 .class(字节码),JVM 才能执行。

JAVA
javac HelloWorld.java
👀 你应该看到
(没有任何输出,目录下多了一个 HelloWorld.class)

没输出就是成功。Java 的规矩:编译通过不打印任何东西。

⚠️ 如果报错
  • 错误: 类 HelloWorld 是公共的, 应在名为 HelloWorld.java 的文件中声明
    → 文件名和类名不一致(大小写也算),改成一致即可。
  • 错误: 需要 ';'
    → 这一行少了分号——Java 每条语句都必须以 ; 结尾。
  • 错误: 找不到符号
    → 变量或方法名拼错、没导入包、或作用域不对。

3③ 运行

🎯 用 java 命令运行类(不带 .class 后缀)。

JAVA
java HelloWorld
👀 你应该看到
Hello, Java!

看到这行输出,说明整条链路通了。

⚠️ 如果报错
  • 错误: 找不到或无法加载主类 HelloWorld
    → 当前目录不对(用 cd 进到 .class 所在目录),或 java 后面多写了 .class。
  • 错误: 在类 HelloWorld 中找不到 main 方法
    → main 写错了:拼写、参数、static、void 任一不对都不行。
✅ 过关标准能不看教程默写出 HelloWorld 并跑出结果,就过关。

第 2 关 · 变量、类型与输出(6 分钟)

目标程序的本质是“数据 + 操作”。先把数据存进变量、再打印出来。
前提:第 1 关完成

1① 声明不同类型的变量

🎯 Java 是强类型语言:变量必须先声明类型、后使用。

JAVA
public class VarDemo {
    public static void main(String[] args) {
        int age = 20;                  // 整数
        double score = 89.5;           // 小数
        char sex = '男';                // 字符,单引号
        boolean pass = true;           // 布尔
        String name = "张三";           // 字符串,双引号
        System.out.println(name + " " + age + " " + score);
        System.out.printf("%s 的成绩是 %.1f%n", name, score);
    }
}
👀 你应该看到
张三 20 89.5
张三 的成绩是 89.5

println 拼接字符串;printf 用 %s/%d/%.1f 占位,%n 是换行。

⚠️ 如果报错
  • 错误: 不兼容的类型: double 无法转换为 int
    → 把小数赋给 int。要么改类型,要么强制转换 (int)89.5。
  • 字符用了双引号
    → char 用单引号 '男',String 用双引号 "男"。

2② 类型转换

🎯 小范围能自动转大范围,反过来必须强制转换(可能丢精度)。

JAVA
int a = 10;
double b = a;          // 自动转换
int c = (int) 9.99;    // 强制转换,结果是 9
System.out.println(c);
👀 你应该看到
9

强制转换是“截断”不是“四舍五入”。

3③ 从键盘读一个数

🎯 交互式程序必备(需要 import java.util.Scanner)。

JAVA
import java.util.Scanner;

public class InputDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入年龄:");
        int age = sc.nextInt();
        System.out.println("你明年 " + (age + 1) + " 岁");
    }
}
👀 你应该看到
请输入年龄:20
你明年 21 岁

nextInt 读整数,nextDouble、nextLine 分别读小数与整行。

⚠️ 如果报错
  • Exception in thread "main" java.util.InputMismatchException
    → 输入的不是数字。要么输数字,要么用 nextLine 再自己解析。
✅ 过关标准能说清 int/double/char/String/boolean 各自怎么声明、怎么输出。

第 3 关 · 流程控制与数组(7 分钟)

目标让程序会判断、会重复、会批量处理数据。
前提:第 2 关完成

1① if-else 判断

🎯 按成绩分档,这是最常用的分支结构。

JAVA
int score = 85;
if (score >= 90) {
    System.out.println("优秀");
} else if (score >= 60) {
    System.out.println("及格");
} else {
    System.out.println("不及格");
}
👀 你应该看到
及格

条件从上往下判断,命中一个就不再往下走。

2② for 循环 + 数组

🎯 数组长度固定,用下标访问(从 0 开始)。

JAVA
int[] scores = {85, 92, 78, 60};
int sum = 0;
for (int i = 0; i < scores.length; i++) {
    sum += scores[i];
}
double avg = (double) sum / scores.length;
System.out.println("总分 " + sum + ",平均 " + avg);
👀 你应该看到
总分 315,平均 78.75

scores.length 是长度,不是 length()。

⚠️ 如果报错
  • Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
    → 下标越界:循环条件写成 i <= length 就会多跑一次,改成 i < length。

3③ while 与 break/continue

🎯 不定次数的循环用 while;break 跳出、continue 跳过本次。

JAVA
int i = 1;
while (i <= 5) {
    if (i == 3) { i++; continue; }
    System.out.print(i + " ");
    i++;
}
👀 你应该看到
1 2 4 5

3 被 continue 跳过了。死循环是 while 最常见的事故,记得改循环变量。

✅ 过关标准能写出 for 求和、if 分支,知道数组下标从 0 开始。

第 4 关 · 类与对象(8 分钟)

目标Java 的核心思维:把“学生”抽象成类,用对象装数据、用方法装行为。
前提:第 3 关完成

1① 写一个 Student 类

🎯 属性私有(封装),通过 getter/setter 访问,构造方法负责初始化。

JAVA
public class Student {
    private String name;
    private int age;
    private double score;

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() { return name; }
    public double getScore() { return score; }

    public String toString() {
        return name + "(" + age + "岁, " + score + "分)";
    }
}
👀 你应该看到
(编译通过:javac Student.java)

this.name 用来区分成员变量与参数名。

2② 创建对象并调用方法

🎯 用 new 创建对象,通过对象名.方法 调用。

JAVA
public class TestStudent {
    public static void main(String[] args) {
        Student s1 = new Student("张三", 20, 89.5);
        Student s2 = new Student("李四", 21, 92);
        System.out.println(s1);
        System.out.println(s2.getName() + " 的成绩:" + s2.getScore());
    }
}
👀 你应该看到
张三(20岁, 89.5分)
李四 的成绩:92.0

new 在堆里创建对象,变量里存的是引用地址。

⚠️ 如果报错
  • NullPointerException
    → 对象还没 new 就调用方法,先创建对象。
  • 错误: 无法将类 Student 中的构造器应用到给定类型
    → 参数个数或类型对不上,检查构造方法签名。

3③ 对象数组

🎯 多个同类对象用数组存起来,配合循环批量处理。

JAVA
Student[] arr = {
    new Student("张三", 20, 89.5),
    new Student("李四", 21, 92),
};
double sum = 0;
for (Student s : arr) sum += s.getScore();
System.out.println("平均分:" + sum / arr.length);
👀 你应该看到
平均分:90.75

for (类型 变量 : 数组) 是增强 for 循环。

✅ 过关标准能独立写出“类 + 构造方法 + getter + 对象数组遍历”,OOP 入门就到位了。

第 5 关 · 集合与文件读写(8 分钟)

目标实际项目里数据不是几个变量,而是一堆;处理完还要存到文件。
前提:第 4 关完成

1① ArrayList 存一组对象

🎯 ArrayList 是长度可变、有顺序的集合(相比数组更常用)。

JAVA
import java.util.ArrayList;

ArrayList<Student> list = new ArrayList<>();
list.add(new Student("张三", 20, 89.5));
list.add(new Student("李四", 21, 92));
list.add(new Student("王五", 19, 78));
System.out.println("共 " + list.size() + " 人");
for (Student s : list) System.out.println(s);
👀 你应该看到
共 3 人
张三(20岁, 89.5分)
李四(21岁, 92.0分)
王五(19岁, 78.0分)

<Student> 是泛型,限定集合里只能放 Student。

⚠️ 如果报错
  • 错误: 需要 ';' / 不兼容的类型
    → 忘了导包 import java.util.ArrayList;。

2② HashMap 按键取值

🎯 需要“按名字查成绩”这种场景,用 Map。

JAVA
import java.util.HashMap;
import java.util.Map;

Map<String, Double> map = new HashMap<>();
map.put("张三", 89.5);
map.put("李四", 92.0);
System.out.println(map.get("李四"));
for (Map.Entry<String, Double> e : map.entrySet()) {
    System.out.println(e.getKey() + " -> " + e.getValue());
}
👀 你应该看到
92.0
张三 -> 89.5
李四 -> 92.0

Map 的键唯一,重复 put 同一个键会覆盖。

3③ 把数据写到文件

🎯 用字符流 + 缓冲流写文本,不用手动 close(try-with-resources 会自动关)。

JAVA
import java.io.*;

try (BufferedWriter bw = new BufferedWriter(new FileWriter("students.txt"))) {
    bw.write("张三,89.5");
    bw.newLine();
    bw.write("李四,92");
    System.out.println("写入完成");
} catch (IOException e) {
    e.printStackTrace();
}
👀 你应该看到
写入完成

文件出现在项目根目录(或当前工作目录)。

⚠️ 如果报错
  • IOException: 系统找不到指定的路径
    → 文件所在目录不存在,先 mkdir 或用绝对路径。

4④ 读回来

🎯 用 BufferedReader 逐行读,这是最通用的读文本方式。

JAVA
try (BufferedReader br = new BufferedReader(new FileReader("students.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}
👀 你应该看到
张三,89.5
李四,92

readLine() 读到文件末尾返回 null,所以循环条件这样写。

✅ 过关标准能把“对象 → 集合 → 文件”串起来,就已经能写课程作业了。

常见报错速查 Ctrl+F 搜报错关键字

报错原因解决
'javac' 不是内部或外部命令,也不是可运行的程序JDK 的 bin 目录没加进 PATH把 %JAVA_HOME%\bin 加到系统变量 Path,重开命令行
错误: 类 X 是公共的, 应在名为 X.java 的文件中声明文件名与 public 类名不一致把文件名改成与类名完全一致(含大小写)
错误: 需要 ';'语句末尾漏了分号(中文分号也不行)补英文分号,检查是否用了中文标点
错误: 找不到符号变量/方法名拼错,或没导入包,或作用域不对检查拼写、import、变量是否在方法内声明
错误: 不兼容的类型类型不匹配(如把 double 赋给 int)改类型或用强制转换 (int)
错误: 找不到或无法加载主类 X当前目录不对,或加了 .class 后缀cd 到 .class 所在目录,java 后只写类名
错误: 在类 X 中找不到 main 方法main 签名写错必须是 public static void main(String[] args)
java.lang.NullPointerException对象还没 new 就调用方法/属性先创建对象,或加 null 判断
java.lang.ArrayIndexOutOfBoundsException数组下标越界循环条件用 i < arr.length
java.util.InputMismatchException输入类型与读取方法不匹配用 nextLine 读整行再自己转换
错误: 缺少返回语句有返回值的方法在某些分支没 return保证每条路径都有 return
错误: 未报告的异常错误 X; 必须对其进行捕获或声明以便抛出受检异常没处理用 try-catch 捕获,或在方法签名上 throws
java.lang.ClassNotFoundException: com.mysql.jdbc.DriverJDBC 驱动 jar 没导入把 mysql-connector-java.jar 加到项目的 Build Path
java.lang.NoClassDefFoundError类在编译时存在、运行时找不到检查 classpath、jar 是否随程序一起部署

完成自检清单

  • ☐ 能用 javac 编译、java 运行一个类
  • ☐ 能声明变量、做类型转换、用 printf 格式化输出
  • ☐ 能写 if-else、for、while,会用数组
  • ☐ 能定义类、写构造方法、创建对象并调用方法
  • ☐ 能用 ArrayList 与 HashMap 存数据
  • ☐ 能用 BufferedReader/Writer 读写文本文件
  • ☐ 看到异常信息能定位到哪一行、什么原因