免费java教程怎么学:从基础语法到第一个小项目

星座8小时前发布 jdkjadmin
0 00
免费java教程怎么学:从基础语法到第一个小项目

免费java教程怎么学:从基础语法到第一个小项目

学 Java 不一定要先买课程,也不必一开始就配置复杂的开发环境。官方文档、免费的 OpenJDK 发行版和命令行工具已经足够完成入门。更重要的是按顺序学习:先让程序运行起来,再练语法和调试,最后做一个范围明确的小项目。

本文会从适用场景和学习准备讲起,逐步介绍 Java 基础语法,并带你完成一个可运行的命令行待办程序。示例以 Java 17 或更高版本为准,尽量使用标准库,不依赖付费软件和第三方框架。

一、先判断 Java 是否适合你

Java 常用于企业后台服务、业务系统、金融与电商平台、Android 开发、数据处理工具和各类长期维护的软件。它有成熟的生态,类型检查较严格,适合学习面向对象编程,也适合开发需要多人协作、长期迭代的项目。

但 Java 不是所有问题的最佳选择。写一次性的小型脚本,Python 或 Shell 可能更省事;做浏览器界面,通常要学习 HTML、CSS 和 JavaScript;开发 Android 应用时,Java 仍可用,但 Kotlin 也是常见选择。选语言时要看目标岗位、项目环境和团队技术栈,而不只是比较语言排名。

如果你的目标是学会编程,Java 是合适的起点之一;如果目标是尽快做出网站,Java 只覆盖服务端的一部分,还需要了解 HTTP、数据库、前端或模板技术。后文的小项目重点是语言基础,不会替代这些知识。

二、免费学习需要准备什么

1. 安装 JDK

JDK 是 Java Development Kit,包含编译器等开发工具。初学者需要安装 JDK,而不只是安装运行环境。可以选择 OpenJDK 发行版,例如 Eclipse Temurin、Microsoft Build of OpenJDK、Amazon Corretto 等。它们提供免费的下载选项,但各自的许可、支持周期和更新政策可能不同;用于商业部署前,应阅读对应发行版的许可说明。

Oracle JDK 的许可和使用条件会随版本、用途及协议变化,不应笼统地说“所有 Oracle JDK 都免费”或“都不能商用”。入门时可选一个符合自己用途的 OpenJDK 发行版,并从其官方网站下载。不要从来源不明的软件下载站安装开发工具。

建议选择 Java 17 或 Java 21 这样的长期支持版本。安装完成后,在终端或命令提示符执行:

java -version
javac -version

两条命令都应能显示版本信息。java 用于启动 Java 程序,javac 用于编译源代码。如果系统提示命令不存在,通常是 JDK 没安装成功,或其可执行文件目录没有加入 PATH。不同操作系统的配置方式不一样,应按所用发行版的安装说明设置,不要直接照搬其他系统的路径。

2. 选择编辑工具

刚开始可以使用文本编辑器和终端,也可以使用 IntelliJ IDEA Community Edition、Visual Studio Code 等工具。工具并不决定你是否学得会 Java。初学时建议至少用命令行编译运行几次,知道源文件、编译器和运行时分别做什么;之后再使用 IDE 的自动补全、调试器和项目管理功能。

3. 认识编译与运行

Java 源代码通常保存在以 .java 结尾的文件中。javac 将源代码编译成字节码,常见输出文件以 .class 结尾,再由 Java 虚拟机运行。

新建文件 Hello.java:

public class Hello {
    public static void main(String[] args) {
        System.out.println("你好,Java!");
    }
}

在文件所在目录执行:

javac Hello.java
java Hello

这里的类名 Hello 与文件名 Hello.java 一致。Java 对大小写敏感,Hello 和 hello 是不同名称。运行时写类名,不写 .class 后缀。

三、基础语法:先掌握常用部分

1. 变量与类型

变量保存程序运行中的数据。常见基本类型包括整数 int、长整数 long、小数 double、单个字符 char 和真假值 boolean。文本通常使用引用类型 String。

public class Variables {
    public static void main(String[] args) {
        String name = "小林";
        int age = 20;
        double price = 12.5;
        boolean active = true;

        System.out.println(name + ",年龄:" + age);
        System.out.println("价格:" + price + ",启用:" + active);
    }
}

变量要先声明再使用。局部变量必须在使用前赋值;类的字段则有默认值。不同数值类型的取值范围不同,超出范围可能导致编译错误或数值溢出。涉及金额时,不建议用 double 直接做精确财务计算;可根据场景使用以最小货币单位保存的整数,或使用 BigDecimal 并明确舍入规则。

2. 运算、比较与字符串

算术运算符包括 +、-、*、/ 和 %。整数除法会丢掉小数部分,例如 5 / 2 的结果是 2,不是 2.5。比较通常得到布尔值,逻辑运算常用 &&(并且)和 ||(或者)。

字符串拼接可以用 +。比较字符串内容时使用 equals,不要用 == 判断文本内容是否相同。== 对对象比较的是引用是否相同,这和字符串内容相等不是一回事。

String input = "yes";

if ("yes".equals(input)) {
    System.out.println("用户确认了");
}

将常量文本写在前面,可以避免 input 为 null 时调用 equals 抛出空指针异常。

3. 条件与循环

if 和 else 用于分支判断,for、while 用于重复执行。循环必须有明确的结束条件,否则可能无限运行。

int score = 76;

if (score >= 60) {
    System.out.println("通过");
} else {
    System.out.println("未通过");
}

for (int i = 1; i <= 3; i++) {
    System.out.println("第 " + i + " 次");
}

在 Java 代码中,比较大小使用 >、<、>= 和 <=。本文 HTML 中的代码已将尖括号转义,浏览器会显示为正常代码字符。

4. 方法:把重复逻辑收起来

方法可以接收参数并返回结果。返回类型写在方法名前;没有返回值时使用 void。下面的 add 方法接收两个整数并返回它们的和:

public static int add(int a, int b) {
    return a + b;
}

方法参数类型和数量会影响调用方式。调用时传入的参数必须匹配,或者能按 Java 规则转换。方法可以有多个同名版本,但参数列表必须不同,这称为方法重载。不要为了让代码“看起来高级”而把所有逻辑拆成大量过小的方法;拆分的目的应是让每个方法职责清楚、便于测试。

5. 数组与集合

数组长度固定,适合保存数量确定的一组数据。需要动态增删元素时,常用 ArrayList。集合使用泛型指定元素类型,能在编译阶段发现一部分类型错误。

import java.util.ArrayList;
import java.util.List;

public class ListExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("阿青");
        names.add("小周");

        for (String name : names) {
            System.out.println(name);
        }
    }
}

泛型中的类型参数不能直接写基本类型,例如用 List<Integer> 而不是 List<int>。Java 会在适当场景自动装箱和拆箱,但这不代表基本类型与包装类型在所有情况下都完全一样。

四、理解类与对象

类描述一类对象具有的数据和行为;对象是按类创建出来的具体实例。初学面向对象时,可以先关注三个概念:字段保存状态,构造方法负责初始化,实例方法操作对象状态。

public class Book {
    private String title;

    public Book(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public static void main(String[] args) {
        Book book = new Book("Java 入门");
        System.out.println(book.getTitle());
    }
}

private 表示字段只在类内部直接访问,外部通过公开方法使用数据。这种封装有助于约束对象状态。this.title 指当前对象的字段,右侧的 title 是构造方法参数。

入门阶段不必急着学习复杂继承体系、设计模式和框架。先能写出职责清晰的小类,再学习接口、组合和继承的适用边界。很多项目中,组合比层层继承更容易维护。

五、异常与输入:程序不能假设用户总是正确操作

异常用于表示运行中出现的问题。比如把非数字文本转换成整数会失败。程序可以捕获预期内、能够合理处理的异常,但不应把所有异常都吞掉,否则错误被隐藏,排查会更困难。

String text = "abc";

try {
    int number = Integer.parseInt(text);
    System.out.println(number);
} catch (NumberFormatException e) {
    System.out.println("请输入有效整数");
}

注意:异常处理不等于输入验证。对用户输入,应先验证格式、长度和允许范围,再进行后续操作。对文件、网络和数据库等外部资源,还要处理可能出现的权限、连接或数据格式问题。

六、第一个小项目:命令行待办清单

接下来做一个单文件的待办程序。它可以新增任务、列出任务、标记任务完成和退出。任务只保存在程序运行期间的内存中,退出后不会保留;这是有意设置的边界,暂时不引入文件或数据库,先练习语法、集合、类和输入处理。

将以下代码保存为 TodoApp.java。代码面向 Java 17 或更高版本,使用 Java 标准库,无须下载第三方依赖。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class TodoApp {
    private static final class Task {
        private final String title;
        private boolean done;

        private Task(String title) {
            this.title = title;
            this.done = false;
        }

        private void markDone() {
            this.done = true;
        }

        @Override
        public String toString() {
            String status = done ? "[已完成]" : "[未完成]";
            return status + " " + title;
        }
    }

    public static void main(String[] args) {
        List<Task> tasks = new ArrayList<>();

        try (Scanner scanner = new Scanner(System.in)) {
            boolean running = true;

            while (running) {
                printMenu();
                System.out.print("请选择:");
                String choice = scanner.nextLine().trim();

                switch (choice) {
                    case "1" -> addTask(scanner, tasks);
                    case "2" -> listTasks(tasks);
                    case "3" -> completeTask(scanner, tasks);
                    case "0" -> {
                        running = false;
                        System.out.println("再见!");
                    }
                    default -> System.out.println("无效选项,请输入 0 到 3。");
                }
            }
        }
    }

    private static void printMenu() {
        System.out.println();
        System.out.println("=== 待办清单 ===");
        System.out.println("1. 新增任务");
        System.out.println("2. 查看任务");
        System.out.println("3. 完成任务");
        System.out.println("0. 退出");
    }

    private static void addTask(Scanner scanner, List<Task> tasks) {
        System.out.print("请输入任务内容:");
        String title = scanner.nextLine().trim();

        if (title.isEmpty()) {
            System.out.println("任务内容不能为空。");
            return;
        }

        tasks.add(new Task(title));
        System.out.println("已添加。");
    }

    private static void listTasks(List<Task> tasks) {
        if (tasks.isEmpty()) {
            System.out.println("目前没有任务。");
            return;
        }

        for (int i = 0; i < tasks.size(); i++) {
            System.out.println((i + 1) + ". " + tasks.get(i));
        }
    }

    private static void completeTask(Scanner scanner, List<Task> tasks) {
        if (tasks.isEmpty()) {
            System.out.println("目前没有可完成的任务。");
            return;
        }

        listTasks(tasks);
        System.out.print("请输入要完成的任务编号:");
        String input = scanner.nextLine().trim();

        try {
            int number = Integer.parseInt(input);

            if (number < 1 || number > tasks.size()) {
                System.out.println("编号超出范围。");
                return;
            }

            tasks.get(number - 1).markDone();
            System.out.println("任务已完成。");
        } catch (NumberFormatException e) {
            System.out.println("请输入有效的整数编号。");
        }
    }
}

在保存文件的目录打开终端,执行:

javac TodoApp.java
java TodoApp

如果你使用的 Java 版本低于 17,代码中的箭头式 switch 写法可能无法编译。最简单的办法是安装 Java 17 或更高版本;也可以把 switch 改写成传统的 case、冒号和 break 形式。先用 java -version 核对实际运行的版本。

代码中有哪些知识点

  • Task 是一个内部类,描述任务的标题和完成状态。
  • List<Task> 保存多个任务,ArrayList 提供动态长度的列表实现。
  • Scanner 从标准输入读取文本。每次用 nextLine() 读取整行,避免混用读取数字与读取整行时常见的换行问题。
  • switch 根据菜单选项分派操作;循环使菜单可以重复出现。
  • 完成任务时,程序把用户输入转换成整数,再检查编号是否在有效范围内。
  • try 后的括号是 try-with-resources。程序离开代码块时会关闭 Scanner,释放相关资源。

此程序对任务内容只检查了是否为空,没有设置字符长度上限;它只适合本地练习,不包含登录、权限、加密、并发控制、数据持久化或输入内容的安全过滤。它不会执行任务文本,因此普通文字不会因为含有命令字符就自动变成系统命令。不过,若以后把输入拼接进 SQL、Shell 命令、网页 HTML 或其他解释器,必须根据具体场景采用参数化接口或正确的上下文转义,不能把这段输入处理直接当成安全方案。

可以怎样继续扩展

按难度逐步增加功能,而不是一次加入数据库和框架:

  1. 为任务增加编号,避免删除或排序后编号含义变化。
  2. 增加删除任务功能,并检查输入编号是否有效。
  3. 把任务保存到本地文本文件或结构化数据文件,重启后再读取。文件读写要处理路径、编码和异常;不要假设任意文件路径都可信。
  4. 添加单元测试,测试空任务列表、无效编号和完成任务等边界。
  5. 再学习 Maven 或 Gradle 管理依赖,之后按目标学习 Web 框架和数据库。

七、初学者常见错误与排查方法

1. 文件名、类名或大小写不一致

包含 public 顶层类的源文件,文件名应与类名一致。例如 public class TodoApp 应保存为 TodoApp.java。Java 区分大小写,TodoApp 和 Todoapp 不是同一个名字。

2. 把编译错误当成运行错误

javac 报错时,程序通常还没有成功编译。先看错误信息中的文件名、行号和具体提示,再检查该行附近是否少了分号、括号或引号。编译通过后,运行阶段仍可能出现逻辑错误或异常;二者需要分开排查。

3. 忘记语句结束符或括号

多数 Java 语句以分号结束,代码块用花括号包围。IDE 可以提示括号配对,但不要只依赖自动修复。遇到错误时,从最近修改的几行开始检查,通常比从头重写更快。

4. 用 == 比较字符串内容

字符串内容比较应使用 equals,并考虑对象可能为 null。例如 "ok".equals(value) 在 value 为 null 时不会因接收者为空而报错。

5. 输入内容未经校验就转换

用户输入不一定是数字,也不一定在有效范围内。先捕获转换失败的情况,再检查范围。项目涉及费用、次数、文件大小等参数时,除了类型正确,还要明确业务允许的上下限,不能只依赖编译器。

6. 只会照抄,不会验证

运行示例后,主动测试空输入、输入字母代替编号、输入不存在的编号、连续添加多个任务等情况。对照预期结果观察程序行为。把代码中的一处逻辑改动,再重新编译和运行,是理解语法比单纯阅读更有效的方式。

八、免费学习路线与查资料方法

免费资料很多,但建议一次只跟一套主线,遇到具体问题再查文档。可以参考 dev.java 上的 Java 学习资料、Oracle Java 文档以及所选 JDK 发行版的安装说明。Oracle 文档是有价值的技术参考,不等于其所有产品版本、服务和许可条件相同;阅读资料与决定部署许可是两件事。

入门路线可以按以下顺序推进:

  1. 第一阶段:运行程序。安装 JDK,掌握文件、类、main 方法、编译和运行。
  2. 第二阶段:掌握语法。练习变量、运算、条件、循环、方法、数组、集合与字符串。
  3. 第三阶段:理解对象。练习类、对象、构造方法、封装、接口和异常处理。
  4. 第四阶段:完成小项目。做待办清单、通讯录或命令行记账练习,并主动处理错误输入。
  5. 第五阶段:补工程能力。学习 Git、构建工具、测试、文件或数据库,再按目标进入后端或 Android 开发。

查资料时,尽量先确认 Java 版本,再把错误信息中的关键部分、相关代码和操作系统一起搜索。不要只复制陌生答案里的命令;尤其是要求管理员权限、删除文件、修改环境变量或访问网络的操作,应先弄清它具体会做什么。

结语

学 Java 的关键不是背完所有语法,而是能解释程序为什么这样运行,并在出错时找到原因。从安装 JDK、编译一个 Hello 程序开始,再逐步掌握类型、流程控制、方法、集合和类,最后完成一个有明确边界的小项目。本文的待办清单可以直接运行,也可以作为练习底稿;当你能独立增加功能并覆盖无效输入时,就已经从“看懂示例”迈向了真正的编程实践。

© 版权声明

相关文章