制器坊 编程基础

Java 基础:JDK、编译、运行与异常堆栈

确认 JDK 可用,并区分源码、字节码与运行命令。配合操作示例、图解和检查点,完成第一次练习,再逐步排查使用中的问题。

信息层级:【有据可查】= 附官方文档或可信来源链接;【社区共识】= 社区用户普遍经验,未经官方确认;【待考察/推测】= 推测或暂未能核实,请谨慎对待。

官方文档:Dev.java 学习站、Java SE API 文档。【有据可查】


1. Java 用在哪?

【社区共识】企业后端(Spring)、安卓开发(与 Kotlin 并存)、大数据(Hadoop/Spark 生态)、《我的世界》Java 版模组。特点:强类型、跨平台("一次编写,到处运行")、生态庞大。

图 1

2. Hello World

// Hello.java —— 文件名必须与 public 类名一致
import java.util.List;

public class Hello {
    public static void main(String[] args) {
        List<String> names = List.of("Alice", "Bob");
        for (String n : names) {
            System.out.println("Hello, " + n + "!");
        }
    }
}
javac Hello.java && java Hello
# 较新 JDK 也可直接:java Hello.java(单文件源码运行)

【有据可查】单文件源码启动见 JEP 330。


3. 语法速查

主题 示例 说明
基本类型 int、long、double、boolean、char 小写为基本类型
包装类型 Integer、Double 集合里只能放对象
字符串 String s = "hi"; s.equals("hi") 比较内容用 equals,不要用 ==
局部类型推断 var list = new ArrayList<String>(); Java 10+
类与对象 class Dog { private String name; Dog(String n){ name = n; } } —
接口 interface Shape { double area(); } —
记录 record Point(int x, int y) {} 不可变数据类(Java 16+)
lambda names.forEach(n -> System.out.println(n)); —
Stream nums.stream().filter(n -> n > 2).map(n -> n * 2).toList() 集合处理
异常 try { } catch (IOException e) { } finally { } 受检异常必须处理或声明 throws
switch 表达式 var r = switch (x) { case 1 -> "one"; default -> "other"; }; Java 14+

4. 常用类库

包 常用类 用途
java.lang String、Math、Integer.parseInt、System.out 默认导入
java.util ArrayList、HashMap、HashSet、List.of、Optional、Scanner 集合与工具
java.util.stream Stream、Collectors 流式处理
java.nio.file Files.readString、Files.writeString、Path.of 文件
java.time LocalDate、LocalDateTime、Duration 日期时间
java.net.http HttpClient 网络请求(Java 11+)
java.util.concurrent ExecutorService、CompletableFuture 并发

5. 读懂报错

5.1 编译错误

Hello.java:6: error: cannot find symbol
        Sytem.out.println("hi");
        ^
  symbol:   variable Sytem
  location: class Hello
报错 原因
cannot find symbol 拼写错误、缺 import、变量未声明
incompatible types: String cannot be converted to int 类型不匹配
';' expected 漏分号
class X is public, should be declared in a file named X.java 文件名与类名不一致
unreported exception IOException; must be caught or declared to be thrown 受检异常未处理
missing return statement 有分支没返回

5.2 运行时异常堆栈

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "name" is null
    at com.example.App.greet(App.java:15)
    at com.example.App.main(App.java:8)
Caused by: ...
图 2
异常 含义
NullPointerException 对 null 调用方法;新版 JDK 会说明是哪个变量为 null
ArrayIndexOutOfBoundsException / IndexOutOfBoundsException 越界
ClassCastException 强制类型转换失败
NumberFormatException Integer.parseInt("abc")
ConcurrentModificationException 遍历时修改集合
ClassNotFoundException / NoClassDefFoundError 类路径(classpath)或依赖缺失
OutOfMemoryError 内存不足或泄漏
UnsupportedClassVersionError 用新 JDK 编译、旧 JDK 运行

【有据可查】更详细的空指针消息见 JEP 358。


6. 构建工具

【社区共识】真实项目用 Maven(pom.xml)或 Gradle(build.gradle)管理依赖。依赖下载失败、版本冲突是 AI 生成项目最常见的"跑不起来"原因——把构建工具的完整输出交给 AI。


7. 本篇无法核实/需谨慎的点

  • 不同 JDK 版本(8/11/17/21/25)语法特性差异较大,示例按较新 LTS 编写。
  • 安卓开发使用的 Java API 与标准 JDK 并不完全一致。

小白练习:把本文流程逐项走通

练习目标:确认 JDK 可用,并区分源码、字节码与运行命令。

上文已介绍概念、配置和操作示例。下面侧重第一次实际操作时的顺序、检查点和结果核对;需要查具体参数时回到对应小节。命令逐条输入,看到上一条的结果后再继续。

  1. 安装与操作系统匹配的 JDK,再分别运行 java --version 和 javac --version。只有 java 可用时继续检查 JDK 与 PATH。

    补充说明:java 负责运行,javac 负责编译。示例的 List.of 至少需要支持该 API 的 JDK;速查表中的较新语法还有各自版本要求。

  2. 新建目录,把原文代码保存成 Hello.java;文件名和 public class Hello 大小写必须一致。

    补充说明:保存上文完整示例,采用 UTF-8。Windows 显示实际扩展名,确认不是 Hello.java.txt;类名与文件名的大小写必须一致。

  3. 切换终端到该目录,单独运行 javac Hello.java。出现编译错误时先修正,再重新编译。

    补充说明:编译成功后查看文件夹,确认生成了 Hello.class。编译错误未修复时,不继续执行旧字节码。

  4. 确认生成 Hello.class 后运行 java Hello;这里填写类名,不加 .class 后缀。

    补充说明:较新 JDK 的 java Hello.java 是另一种源码启动方式;初次练习先分开编译和运行,便于辨认输入对象。

  5. 预期得到 Alice 和 Bob 两行问候。修改源码后先重新编译,再运行,避免继续执行旧字节码。

    补充说明:完整输出应为 Hello, Alice! 与 Hello, Bob!。main 是入口,List.of 创建名单,for 逐个取出名字,System.out.println 输出并换行。

  6. 出现版本错误时核对编译与运行使用的 JDK;出现异常时沿自己的文件行和 Caused by 继续找原因。

    补充说明:速查表中的 ArrayList 等类型需要相应导入,片段变量需要定义。异常定位时保留自己的 at 行及各层 Caused by,不要只复制最后一个类名。

继续浏览制器坊 返回顶部 ↑
教程图解100%
教程图解
灵犀台