来自许老师的宝藏秘籍-1

目录

image-20210918163916987

1.前言

搭好了 Java 开发环境,我们就实战一下,来写一个 Java 应用程序,程序运行的时候能看到 ​Hello World 的输出,同时分析下从编码到运行的整个过程,都发生了什么。

2.编码输出 Hello World

我们不借助任何集成开发环境,就用最原始的手写的方式来编码。
Windows 用户可以直接打开记事本,macOS 用户可以在控制台键入以下命令来打开记事本:

1
open -a TextEdit 

以下是输出 Hello World 应用程序的极简代码。

1
2
3
4
5
public class HelloWorld{ 
public static void main(String[] args){
System.out.println("Hello, World!!!");
}
}
image-20210918164226253

保存文件命名为 HelloWorld.java,代表这是 Java 源码文件。

3.编译源码文件

Java 文件只是源码文件,还不能执行,必须将它转换成字节码文件,也就是 .class 文件才能够执行。这个转换的过程就是编译。
编译指令是 javac,c 就是 compile(编译) 的首字母。

image-20210918164338514
执行以下命令,HelloWorld.java 文件会被编译,同目录下就会生成 HelloWorld.class 文件。

1
javac HelloWorld.java 
1

4.执行字节码文件

.class 文件生成,而且该文件内部有 main 函数,说明有程序执行的入口,那其实意味着 Hello World 程序已经写好并且达到可运行的状态了。
那怎么跑这个 Java 程序呢?
很简单,通过 java 命令即可,命令的参数就是 类名,如下:

1
java HelloWorld 
image-20210918164502899

控制台打印了 Hello, World!!!

image-20210918164535269

这意味着我们成功实现第一个 Java 应用程序,并顺利运行。

那么整个过程是怎么发生的呢,我们来分析一下。

5.代码分析

1
2
3
4
5
public class HelloWorld{ 
public static void main(String[] args){
System.out.println("Hello, World!!!");
}
}

这里有三个 Java 的关键字,分别是 public、class 和 static。
public 是 Java 语法中的访问权限修饰符,后边我们会再学到,这里先简单提下。

public(公共的) 的兄弟还有** protected**(受保护的)、default(默认的) 和 private(私有的),他们决定了 Java 世界中的 类、对象、方法和属性,能被多大的范围访问,是当前类,还是当前包,还是不受限的哪里都能访问。

简单来说就是一种权限控制,类似你发朋友圈,可以选择完全公开,可以选择部分人可见,也可以选择仅自己可见。
回到源码,我们看到 public 修饰了 HelloWorld 这个类以及 main 这个方法。也正是 public,让我们执行程序时,没有遭到阻拦。
​

class(类)表明当前源码文件是个普通类,这个关键词是最常用的,它的兄弟还有interface(接口类)和 enum(枚举类)。
​

class 后边的 HelloWorld 就是编码时为当前这个类起的名字。按照命名规范,类名是字母和数字的组合,首个字符必须是大写字母。
​

类名后面的花括号即 {} 里边的内容就是类的定义。
​

static 是静态修饰符,表明被修饰的内容可以被当前的类直接引用,而不需要将类实例化。此处修饰了 main 方法,表明 main 方法可以直接被 HelloWorld 引用。
​

void 是 main 方法的返回值,此处表示无返回值。
​

main 圆括号里的内容,就是 main 方法的入参,String[] 说明这是一个字符串数组,args 代表变量。
它的作用就是,启动 Java 应用的同时,能够传递一个 String 类型的数组来定制化应用的初始化属性。比如你在执行 java HelloWorld 这个指令时,可以传入你需要的参数。

image-20210918164650529

方法申明后面的花括号即 {} 里边的内容就是方法的定义,方法的代码每一行用分号结束。

1
System.out.println("Hello, World!!!");

System.out 是 Java 提供的一个静态的打印流对象,通过它可以进行打印相关的操作,在它的基础上,调用 println 方法,就可以在控制台输出指定的信息。
​

接下来我们看下对源代码都做了哪些操作。

6.执行路径分析

image-20210918164745465

一、用 JDK 中的 javac 命令将 Java 源代码进行编译,生成 Java 字节码,也就是 class 文件。
javac 命令在 JDK 目录的 bin 目录下。

image-20210918164840617

二、用 JRE 的 java 命令执行 class 文件时,Java 字节码会被传输到 JVM(Java 虚拟机),JVM 会合并字节码以及 JRE 中的库文件一起执行,输出特定硬件平台的机器码,或者说指令集。

三、机器码被底层物理硬件平台执行。
通过这个过程,我们也会发现,要想做到 Write Once, Run Anywhere(一次编写,到处运行) 这样的跨平台特性,就必须保证 class 文件无论在哪个平台都能正常执行,但不同硬件平台接收的指令集有很大差异,那就需要有个东西基于不同的操作系统平台来做适配,担起这一重任的就是 JVM。

因此,正是 JVM 的不跨平台特性,才实现了 Java 语言的跨平台特性。
​

像刚才的 HelloWorld 的源码,经过编译生成了 HelloWorld.class,然后在 MacOs 上用 java HelloWorld 可以执行它。接着,把 HelloWorld.class 复制到 Linux 环境或者 Windows 环境中,同样用 java HelloWorld 来执行,是可以得到与 MacOs 中相同的结果的。
​

事实上,如果复制 HelloWorld.java 文件到 Linux 环境中,同样 javac,生成的 class 文件也是相同的。
再结合下面这个图,就可以理解为什么我们下载 JDK 要区分操作系统版本了。

image-20210918165020197

7.总结

通过HelloWorld 的一个极简 Java 程序,学习如何写 Java 代码以及如何运行 Java 程序,同时也分析了 Java 源码中涉及到的相关语法和规范,最后从这一切是怎么发生的角度上,分析从源码到运行的整个执行路径,在分析的过程中,帮助我们更深地理解了 Java 的跨平台特性。

有了对 Java 初步的认识和感知后,再学习 Java 的一些概念和语法就会相对得心应手。