第2章 Java 程序是怎么运行起来的

第2章 Java 程序是怎么运行起来的

这一章只解决一个问题:你写的 Java 代码,到底是怎么跑起来的?

如果这个问题不清楚,后面很多概念都会很虚。比如你会不知道为什么要装 JDK,为什么运行前要编译,为什么有 .class 文件,为什么类名和文件名要一致,为什么有时会报"找不到主类"。

我们从一个最小程序开始。

一、写下第一个 Java 文件

创建文件:

text 复制代码
Hello.java

写入:

java 复制代码
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello Java");
    }
}

先不要急着背。我们先运行它。

在文件所在目录执行:

bash 复制代码
javac Hello.java
java Hello

如果一切正常,你会看到:

text 复制代码
Hello Java

这里有两个命令:

  • javac Hello.java
  • java Hello

它们不是一回事。

二、javac 做什么

javac 是 Java 编译器。它读取 .java 源码,生成 .class 字节码文件。

运行:

bash 复制代码
javac Hello.java

目录里会多出:

text 复制代码
Hello.class

执行过程:
#mermaid-svg-MolDTKzWvQp34SFu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MolDTKzWvQp34SFu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MolDTKzWvQp34SFu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MolDTKzWvQp34SFu .error-icon{fill:#552222;}#mermaid-svg-MolDTKzWvQp34SFu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MolDTKzWvQp34SFu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MolDTKzWvQp34SFu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MolDTKzWvQp34SFu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MolDTKzWvQp34SFu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MolDTKzWvQp34SFu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MolDTKzWvQp34SFu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MolDTKzWvQp34SFu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MolDTKzWvQp34SFu .marker.cross{stroke:#333333;}#mermaid-svg-MolDTKzWvQp34SFu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MolDTKzWvQp34SFu p{margin:0;}#mermaid-svg-MolDTKzWvQp34SFu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MolDTKzWvQp34SFu .cluster-label text{fill:#333;}#mermaid-svg-MolDTKzWvQp34SFu .cluster-label span{color:#333;}#mermaid-svg-MolDTKzWvQp34SFu .cluster-label span p{background-color:transparent;}#mermaid-svg-MolDTKzWvQp34SFu .label text,#mermaid-svg-MolDTKzWvQp34SFu span{fill:#333;color:#333;}#mermaid-svg-MolDTKzWvQp34SFu .node rect,#mermaid-svg-MolDTKzWvQp34SFu .node circle,#mermaid-svg-MolDTKzWvQp34SFu .node ellipse,#mermaid-svg-MolDTKzWvQp34SFu .node polygon,#mermaid-svg-MolDTKzWvQp34SFu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MolDTKzWvQp34SFu .rough-node .label text,#mermaid-svg-MolDTKzWvQp34SFu .node .label text,#mermaid-svg-MolDTKzWvQp34SFu .image-shape .label,#mermaid-svg-MolDTKzWvQp34SFu .icon-shape .label{text-anchor:middle;}#mermaid-svg-MolDTKzWvQp34SFu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MolDTKzWvQp34SFu .rough-node .label,#mermaid-svg-MolDTKzWvQp34SFu .node .label,#mermaid-svg-MolDTKzWvQp34SFu .image-shape .label,#mermaid-svg-MolDTKzWvQp34SFu .icon-shape .label{text-align:center;}#mermaid-svg-MolDTKzWvQp34SFu .node.clickable{cursor:pointer;}#mermaid-svg-MolDTKzWvQp34SFu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MolDTKzWvQp34SFu .arrowheadPath{fill:#333333;}#mermaid-svg-MolDTKzWvQp34SFu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MolDTKzWvQp34SFu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MolDTKzWvQp34SFu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MolDTKzWvQp34SFu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MolDTKzWvQp34SFu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MolDTKzWvQp34SFu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MolDTKzWvQp34SFu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MolDTKzWvQp34SFu .cluster text{fill:#333;}#mermaid-svg-MolDTKzWvQp34SFu .cluster span{color:#333;}#mermaid-svg-MolDTKzWvQp34SFu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MolDTKzWvQp34SFu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MolDTKzWvQp34SFu rect.text{fill:none;stroke-width:0;}#mermaid-svg-MolDTKzWvQp34SFu .icon-shape,#mermaid-svg-MolDTKzWvQp34SFu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MolDTKzWvQp34SFu .icon-shape p,#mermaid-svg-MolDTKzWvQp34SFu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MolDTKzWvQp34SFu .icon-shape .label rect,#mermaid-svg-MolDTKzWvQp34SFu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MolDTKzWvQp34SFu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MolDTKzWvQp34SFu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MolDTKzWvQp34SFu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Hello.java

源码
javac编译
Hello.class

字节码

.java 是人写的源码。

.class 是 JVM 能理解的字节码。

如果源码有语法错误,javac 阶段就会失败,不会生成 .class

比如少写分号:

java 复制代码
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello Java")
    }
}

再编译:

bash 复制代码
javac Hello.java

你会看到类似:

text 复制代码
error: ';' expected

这是编译错误。程序还没有运行,编译器已经发现代码不合法。

三、java 做什么

java 命令负责启动 JVM,并让 JVM 执行某个类里的 main 方法。

bash 复制代码
java Hello

注意,这里写的是:

text 复制代码
Hello

不是:

text 复制代码
Hello.java
Hello.class

java Hello 的意思是:请 JVM 找到名为 Hello 的类,并执行它的 main 方法。

执行过程:
#mermaid-svg-cEY1HRITRyG4YBvM{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cEY1HRITRyG4YBvM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cEY1HRITRyG4YBvM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cEY1HRITRyG4YBvM .error-icon{fill:#552222;}#mermaid-svg-cEY1HRITRyG4YBvM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cEY1HRITRyG4YBvM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cEY1HRITRyG4YBvM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cEY1HRITRyG4YBvM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cEY1HRITRyG4YBvM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cEY1HRITRyG4YBvM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cEY1HRITRyG4YBvM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cEY1HRITRyG4YBvM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cEY1HRITRyG4YBvM .marker.cross{stroke:#333333;}#mermaid-svg-cEY1HRITRyG4YBvM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cEY1HRITRyG4YBvM p{margin:0;}#mermaid-svg-cEY1HRITRyG4YBvM .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cEY1HRITRyG4YBvM .cluster-label text{fill:#333;}#mermaid-svg-cEY1HRITRyG4YBvM .cluster-label span{color:#333;}#mermaid-svg-cEY1HRITRyG4YBvM .cluster-label span p{background-color:transparent;}#mermaid-svg-cEY1HRITRyG4YBvM .label text,#mermaid-svg-cEY1HRITRyG4YBvM span{fill:#333;color:#333;}#mermaid-svg-cEY1HRITRyG4YBvM .node rect,#mermaid-svg-cEY1HRITRyG4YBvM .node circle,#mermaid-svg-cEY1HRITRyG4YBvM .node ellipse,#mermaid-svg-cEY1HRITRyG4YBvM .node polygon,#mermaid-svg-cEY1HRITRyG4YBvM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cEY1HRITRyG4YBvM .rough-node .label text,#mermaid-svg-cEY1HRITRyG4YBvM .node .label text,#mermaid-svg-cEY1HRITRyG4YBvM .image-shape .label,#mermaid-svg-cEY1HRITRyG4YBvM .icon-shape .label{text-anchor:middle;}#mermaid-svg-cEY1HRITRyG4YBvM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cEY1HRITRyG4YBvM .rough-node .label,#mermaid-svg-cEY1HRITRyG4YBvM .node .label,#mermaid-svg-cEY1HRITRyG4YBvM .image-shape .label,#mermaid-svg-cEY1HRITRyG4YBvM .icon-shape .label{text-align:center;}#mermaid-svg-cEY1HRITRyG4YBvM .node.clickable{cursor:pointer;}#mermaid-svg-cEY1HRITRyG4YBvM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cEY1HRITRyG4YBvM .arrowheadPath{fill:#333333;}#mermaid-svg-cEY1HRITRyG4YBvM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cEY1HRITRyG4YBvM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cEY1HRITRyG4YBvM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cEY1HRITRyG4YBvM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cEY1HRITRyG4YBvM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cEY1HRITRyG4YBvM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cEY1HRITRyG4YBvM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cEY1HRITRyG4YBvM .cluster text{fill:#333;}#mermaid-svg-cEY1HRITRyG4YBvM .cluster span{color:#333;}#mermaid-svg-cEY1HRITRyG4YBvM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cEY1HRITRyG4YBvM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cEY1HRITRyG4YBvM rect.text{fill:none;stroke-width:0;}#mermaid-svg-cEY1HRITRyG4YBvM .icon-shape,#mermaid-svg-cEY1HRITRyG4YBvM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cEY1HRITRyG4YBvM .icon-shape p,#mermaid-svg-cEY1HRITRyG4YBvM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cEY1HRITRyG4YBvM .icon-shape .label rect,#mermaid-svg-cEY1HRITRyG4YBvM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cEY1HRITRyG4YBvM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cEY1HRITRyG4YBvM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cEY1HRITRyG4YBvM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} java Hello
启动JVM
加载Hello.class
寻找main方法
执行代码

如果你写:

bash 复制代码
java Hello.java

就混淆了源码文件和类名。

四、JDK、JRE、JVM 的关系

学 Java 必须理解这三个词。
#mermaid-svg-R4osv0JxdM4JIQs8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-R4osv0JxdM4JIQs8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-R4osv0JxdM4JIQs8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-R4osv0JxdM4JIQs8 .error-icon{fill:#552222;}#mermaid-svg-R4osv0JxdM4JIQs8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-R4osv0JxdM4JIQs8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-R4osv0JxdM4JIQs8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-R4osv0JxdM4JIQs8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-R4osv0JxdM4JIQs8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-R4osv0JxdM4JIQs8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-R4osv0JxdM4JIQs8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-R4osv0JxdM4JIQs8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-R4osv0JxdM4JIQs8 .marker.cross{stroke:#333333;}#mermaid-svg-R4osv0JxdM4JIQs8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-R4osv0JxdM4JIQs8 p{margin:0;}#mermaid-svg-R4osv0JxdM4JIQs8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-R4osv0JxdM4JIQs8 .cluster-label text{fill:#333;}#mermaid-svg-R4osv0JxdM4JIQs8 .cluster-label span{color:#333;}#mermaid-svg-R4osv0JxdM4JIQs8 .cluster-label span p{background-color:transparent;}#mermaid-svg-R4osv0JxdM4JIQs8 .label text,#mermaid-svg-R4osv0JxdM4JIQs8 span{fill:#333;color:#333;}#mermaid-svg-R4osv0JxdM4JIQs8 .node rect,#mermaid-svg-R4osv0JxdM4JIQs8 .node circle,#mermaid-svg-R4osv0JxdM4JIQs8 .node ellipse,#mermaid-svg-R4osv0JxdM4JIQs8 .node polygon,#mermaid-svg-R4osv0JxdM4JIQs8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-R4osv0JxdM4JIQs8 .rough-node .label text,#mermaid-svg-R4osv0JxdM4JIQs8 .node .label text,#mermaid-svg-R4osv0JxdM4JIQs8 .image-shape .label,#mermaid-svg-R4osv0JxdM4JIQs8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-R4osv0JxdM4JIQs8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-R4osv0JxdM4JIQs8 .rough-node .label,#mermaid-svg-R4osv0JxdM4JIQs8 .node .label,#mermaid-svg-R4osv0JxdM4JIQs8 .image-shape .label,#mermaid-svg-R4osv0JxdM4JIQs8 .icon-shape .label{text-align:center;}#mermaid-svg-R4osv0JxdM4JIQs8 .node.clickable{cursor:pointer;}#mermaid-svg-R4osv0JxdM4JIQs8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-R4osv0JxdM4JIQs8 .arrowheadPath{fill:#333333;}#mermaid-svg-R4osv0JxdM4JIQs8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-R4osv0JxdM4JIQs8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-R4osv0JxdM4JIQs8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-R4osv0JxdM4JIQs8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-R4osv0JxdM4JIQs8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-R4osv0JxdM4JIQs8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-R4osv0JxdM4JIQs8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-R4osv0JxdM4JIQs8 .cluster text{fill:#333;}#mermaid-svg-R4osv0JxdM4JIQs8 .cluster span{color:#333;}#mermaid-svg-R4osv0JxdM4JIQs8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-R4osv0JxdM4JIQs8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-R4osv0JxdM4JIQs8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-R4osv0JxdM4JIQs8 .icon-shape,#mermaid-svg-R4osv0JxdM4JIQs8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-R4osv0JxdM4JIQs8 .icon-shape p,#mermaid-svg-R4osv0JxdM4JIQs8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-R4osv0JxdM4JIQs8 .icon-shape .label rect,#mermaid-svg-R4osv0JxdM4JIQs8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-R4osv0JxdM4JIQs8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-R4osv0JxdM4JIQs8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-R4osv0JxdM4JIQs8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} JDK

开发工具包
JRE

运行环境
JVM

Java虚拟机
javac编译器
其他开发工具

JVM

JVM 是 Java Virtual Machine,Java 虚拟机。它执行 .class 字节码。

JRE

JRE 是 Java Runtime Environment,Java 运行环境。它包含 JVM 和运行 Java 程序需要的基础类库。

JDK

JDK 是 Java Development Kit,Java 开发工具包。它包含 JRE,还包含 javac 等开发工具。

写 Java 需要 JDK。只运行 Java 程序理论上 JRE 就够,但现在日常开发基本都安装 JDK。

检查命令:

bash 复制代码
java -version
javac -version

如果 java 有,javac 没有,说明 JDK 配置可能有问题。

五、为什么 Java 要多一步编译

有些语言可以直接解释执行。Java 通常先编译成字节码,再由 JVM 执行。这样设计有几个好处。

1. 提前发现错误

类型错误、语法错误可以在编译阶段发现。

java 复制代码
int age = "18";

这段代码编译不过,因为字符串不能直接赋给 int。

2. 跨平台

同一份 .class 可以在不同系统上的 JVM 中运行。
#mermaid-svg-sTABA18InOalIRrI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-sTABA18InOalIRrI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sTABA18InOalIRrI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sTABA18InOalIRrI .error-icon{fill:#552222;}#mermaid-svg-sTABA18InOalIRrI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sTABA18InOalIRrI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sTABA18InOalIRrI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sTABA18InOalIRrI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sTABA18InOalIRrI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sTABA18InOalIRrI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sTABA18InOalIRrI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sTABA18InOalIRrI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sTABA18InOalIRrI .marker.cross{stroke:#333333;}#mermaid-svg-sTABA18InOalIRrI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sTABA18InOalIRrI p{margin:0;}#mermaid-svg-sTABA18InOalIRrI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-sTABA18InOalIRrI .cluster-label text{fill:#333;}#mermaid-svg-sTABA18InOalIRrI .cluster-label span{color:#333;}#mermaid-svg-sTABA18InOalIRrI .cluster-label span p{background-color:transparent;}#mermaid-svg-sTABA18InOalIRrI .label text,#mermaid-svg-sTABA18InOalIRrI span{fill:#333;color:#333;}#mermaid-svg-sTABA18InOalIRrI .node rect,#mermaid-svg-sTABA18InOalIRrI .node circle,#mermaid-svg-sTABA18InOalIRrI .node ellipse,#mermaid-svg-sTABA18InOalIRrI .node polygon,#mermaid-svg-sTABA18InOalIRrI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sTABA18InOalIRrI .rough-node .label text,#mermaid-svg-sTABA18InOalIRrI .node .label text,#mermaid-svg-sTABA18InOalIRrI .image-shape .label,#mermaid-svg-sTABA18InOalIRrI .icon-shape .label{text-anchor:middle;}#mermaid-svg-sTABA18InOalIRrI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sTABA18InOalIRrI .rough-node .label,#mermaid-svg-sTABA18InOalIRrI .node .label,#mermaid-svg-sTABA18InOalIRrI .image-shape .label,#mermaid-svg-sTABA18InOalIRrI .icon-shape .label{text-align:center;}#mermaid-svg-sTABA18InOalIRrI .node.clickable{cursor:pointer;}#mermaid-svg-sTABA18InOalIRrI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sTABA18InOalIRrI .arrowheadPath{fill:#333333;}#mermaid-svg-sTABA18InOalIRrI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sTABA18InOalIRrI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sTABA18InOalIRrI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sTABA18InOalIRrI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sTABA18InOalIRrI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sTABA18InOalIRrI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sTABA18InOalIRrI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sTABA18InOalIRrI .cluster text{fill:#333;}#mermaid-svg-sTABA18InOalIRrI .cluster span{color:#333;}#mermaid-svg-sTABA18InOalIRrI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sTABA18InOalIRrI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sTABA18InOalIRrI rect.text{fill:none;stroke-width:0;}#mermaid-svg-sTABA18InOalIRrI .icon-shape,#mermaid-svg-sTABA18InOalIRrI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sTABA18InOalIRrI .icon-shape p,#mermaid-svg-sTABA18InOalIRrI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sTABA18InOalIRrI .icon-shape .label rect,#mermaid-svg-sTABA18InOalIRrI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sTABA18InOalIRrI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sTABA18InOalIRrI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sTABA18InOalIRrI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Hello.class
Windows JVM
macOS JVM
Linux JVM

你写的是 Java,真正和操作系统打交道的是 JVM。

3. 支持大型工程

Java 的编译、包、类、依赖管理,让大型项目更容易组织。虽然入门时显得麻烦,但这是工程化能力的一部分。

六、public class 和文件名为什么要一致

文件:

text 复制代码
Hello.java

代码:

java 复制代码
public class Hello {
}

如果你写:

java 复制代码
public class Demo {
}

但文件叫:

text 复制代码
Hello.java

编译会报错:

text 复制代码
class Demo is public, should be declared in a file named Demo.java

意思是:public 类 Demo 应该放在 Demo.java 文件里。

先记规则:

text 复制代码
public 类名 = 文件名去掉 .java

一个文件里最多只能有一个 public 顶级类。以后大型项目里,一个类通常一个文件。

七、main 方法为什么长这样

java 复制代码
public static void main(String[] args)

这一行初学时最吓人。先拆成几块。

main

main 是方法名。JVM 约定从这个方法开始执行。

如果你写成:

java 复制代码
public static void start(String[] args)

编译可以过,但运行时 JVM 找不到 main 入口。

String\[\] args

这是命令行参数。运行程序时可以传入:

bash 复制代码
java Hello Tom 18

这些参数会进入 args 数组。

public static void

这三个词后面会详细讲。

现在先建立直觉:

  • public:JVM 可以访问这个方法。
  • static:不需要创建对象就能调用。
  • void:方法没有返回值。

第一阶段先把 main 当成固定入口。等学到方法、类和对象,再把它完全拆开。

八、命令行参数实战

代码:

java 复制代码
public class ArgsDemo {
    public static void main(String[] args) {
        System.out.println("参数个数:" + args.length);

        for (int i = 0; i < args.length; i++) {
            System.out.println("第" + i + "个参数:" + args[i]);
        }
    }
}

编译:

bash 复制代码
javac ArgsDemo.java

运行:

bash 复制代码
java ArgsDemo Tom 18 Shanghai

输出:

text 复制代码
参数个数:3
第0个参数:Tom
第1个参数:18
第2个参数:Shanghai

注意:所有命令行参数默认都是字符串。18 进入程序后也是字符串 "18",不是数字 18。

如果要转成数字:

java 复制代码
int age = Integer.parseInt(args[1]);

如果传入的不是数字:

bash 复制代码
java ArgsDemo Tom abc

转换时会报:

text 复制代码
NumberFormatException

这就是运行时错误:代码编译通过,但运行过程中数据不符合预期。

九、package 和 classpath 的第一层理解

小程序可以没有 package:

java 复制代码
public class Hello {
}

项目大了以后会用 package:

java 复制代码
package com.example.course;

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

文件路径通常对应:

text 复制代码
src/com/example/course/Hello.java

编译:

bash 复制代码
javac -d out src/com/example/course/Hello.java

运行:

bash 复制代码
java -cp out com.example.course.Hello

这里:

  • -d out 表示把编译结果放到 out 目录。
  • -cp out 表示 classpath 是 out,JVM 去 out 里找类。
  • com.example.course.Hello 是完整类名。

如果你只写:

bash 复制代码
java Hello

JVM 找不到,因为这个类的完整名字不是 Hello,而是 com.example.course.Hello

入门阶段先知道:package 会影响类的完整名字,classpath 会影响 JVM 到哪里找类。

十、常见错误排查

1. 找不到 javac

text 复制代码
command not found: javac

原因可能是:

  • 没装 JDK。
  • 装了但环境变量没配置。
  • 终端没有重新打开。

先运行:

bash 复制代码
java -version
javac -version

2. 类名和文件名不一致

text 复制代码
class Hello is public, should be declared in a file named Hello.java

检查 public 类名和文件名。

3. 找不到主类

text 复制代码
Error: Could not find or load main class Hello

检查:

  • 是否已经 javac Hello.java
  • 当前目录是否有 Hello.class
  • 运行时是否写了正确类名。
  • 如果有 package,是否写完整类名。
  • classpath 是否正确。

4. 找不到 main 方法

text 复制代码
Main method not found in class Hello

检查 main 是否写成:

java 复制代码
public static void main(String[] args)

大小写、参数、static 都不要乱改。

5. 编译错误和运行错误混淆

编译错误发生在:

bash 复制代码
javac Hello.java

运行错误发生在:

bash 复制代码
java Hello

先判断错误发生在哪一步,排查会快很多。

十一、本章练习

  1. 创建 Hello.java,输出自己的名字。

  2. 故意删除分号,观察编译错误。

  3. 故意把文件名改成 Demo.java,但类名仍然是 Hello,观察错误。

  4. ArgsDemo.java,运行:

bash 复制代码
java ArgsDemo Java Course

观察参数输出。

  1. 创建带 package 的 Hello.java,用 javac -d outjava -cp out 运行。

十二、本章总结

这一章要真正掌握:

  • Java 源码文件是 .java
  • javac 把源码编译成 .class
  • java 启动 JVM 执行 class。
  • JDK 包含开发工具,JVM 执行字节码。
  • public 类名必须和文件名一致。
  • main 方法是程序入口。
  • 命令行参数进入 String[] args
  • package 会影响类的完整名字。
  • classpath 决定 JVM 去哪里找类。
  • 编译错误和运行错误要分开看。

如果你能不用 IDE,只靠命令行独立编译和运行这些例子,就说明你已经真正迈过 Java 入门第一关。