学习Java基础入门
首先
最近有很多宣传着「即使没有经验也可以成为工程师」或者「即使文科出身也可以成为工程师」的编程学校,我在公司的培训中也受益于其中之一。
然而,由于它们主要以在短期内制作应用程序为目标,我感觉它们并没有太注重”基础”这一方面。因此,我打算为即将学习编程的新人,以及像我这样感觉自己”基础”不足的新人工程师,写一份能够作为Java基础入门的材料。
「基础」的意思是
迄今为止,“基础”一词我们都加了括号。
「基础」的意思是指让某物成立的根本部分,即源头。例如:「由于基础扎实,所以进步很快」「打下基础」「基础知识」。
本篇将作为学习Java的”基础”的第一步。
-
- Java和JVM
- 直到显示出”Hello World”为止
我打算将注意力集中在这两个方面上。
Java和JVM
先让我们来看一下Java这种编程语言本身。
Java (只需要一种选项,以中文本地化地复述):
让我们首先简单地回顾一下编程语言本身。
程序员利用编程语言向计算机发送指令。然而,计算机只是一台通过电力运行的计算机。
顺便说一下,计算机这个词在德语中被称为”Rechner”,它来源于动词”rechnen”,意思是”进行计算”。真是个闲话。
据说,由于计算机只能接收到电信号的两个状态——开或关,过去的程序员使用0和1的二进制来编写程序。顺便提一下,由0和1组成的那些东西被称为机器语言。
由于二进制的位数较多,所以常常使用十六进制来表示,但这对人类来说仍然不够友好。因此,为了给机器语言表示的指令赋予类似昵称的东西(被称作”助记符”),产生了一种被称为”汇编语言”的东西。
然而,即使如此,程序仍然对人类来说不够易懂,并且随着时代的发展,需要的程序数量也增加了,复杂性也增加了。因此,我们开始开发更加容易理解的程序编写方法,以便更好地为人类服务。顺便提一下,这种对人类易懂的编程语言被称为”高级语言”,而计算机易于理解的语言则被称为”低级语言”。
人类能够理解的事物,对于计算机来说往往是难以理解的。因此,程序员需要将自己编写的代码转化为计算机可理解的机器语言,这个过程被称为“编译”,执行编译的程序被称为“编译器”。
编译器将用高级语言编写的程序转化为计算机可理解的机器语言,但编译器会根据具体的计算机环境进行编译。换句话说,不同环境的计算机无法理解相同的转化后的机器语言,因此需要一个特定的编译器。
终于在这里见到了Java的出现。
Java是由Sun Microsystems在1995年推出的。Java是一种高级语言,如前所述,需要进行编译并转化为机器语言才能运行,但与其他语言的不同之处在于它使用了Java虚拟机(JVM)。
JVM为计算机分配内存并启动。然后可以在JVM上运行程序,因此无需担心计算机的差异。
更详细地解释一下,Java代码以易于人类理解的方式编写(文件名为hoge.java),然后通过编译转换为称为中间语言的东西(文件名为hoge.class。中间语言这个名称不是官方名称,只是方便起见称之为如此,正确的名称似乎是Java字节码)。
然后,JVM加载这个中间语言,并逐行将其转换为机器语言并执行。这种逐行转换和执行的程序被称为“解释器”1。
换句话说,Java需要经过两次转换过程才能被执行。(一次由编译器,一次由解释器)
JVM
Java虚拟机
在构建Java环境时,我们会遇到JDK和JRE这两个东西。
JDK是Java开发工具包,用于在使用Java进行开发时所需的软件开发工具包。
而JDK中包含的是JRE(Java Runtime Environment),被称为Java运行环境。它是一组用于在计算机上运行Java应用程序的软件,其中包括JVM。
直到“Hello World!”被显示出来。
接下来我们简单地确认一下直到显示”Hello World!”为止的过程。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
让我们首先进行编译。
javac命令将编译java文件并创建class文件。
javac HelloWorld.java
执行上述操作后,将生成一个名为HelloWorld.class的文件。然后,我们首先尝试显示Hello World!通过使用java命令启动JVM,分析并执行被Java字节码编写的HelloWorld.class文件。
$ java HelloWorld
Hello World!
已经完成了。
现在我们来确认一下Java字节码。
通过使用javap命令,可以将class文件转换为人类可读的形式。
$ javap -c HelloWorld
Compiled from "HelloWorld.java"
public class HelloWorld {
public HelloWorld();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello World!
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
这个类以HelloWorld开头,有两个函数,第一个是构造函数,第二个是相当于main函数的字节码。原始代码中没有构造函数,但似乎是自动生成的。让我们来看一下函数的内部。
代码由三部分组成:“索引:指令 #常量池编号”。常量池是Java虚拟机中保存常量和符号的区域,先暂时看一下。
通过在javap命令后加上-v选项可以进行确认。
Constant pool:
#1 = Methodref #6.#15 // java/lang/Object."<init>":()V
#2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #18 // Hello World!
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #21 // HelloWorld
#6 = Class #22 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 main
#12 = Utf8 ([Ljava/lang/String;)V
#13 = Utf8 SourceFile
#14 = Utf8 HelloWorld.java
#15 = NameAndType #7:#8 // "<init>":()V
#16 = Class #23 // java/lang/System
#17 = NameAndType #24:#25 // out:Ljava/io/PrintStream;
#18 = Utf8 Hello World!
#19 = Class #26 // java/io/PrintStream
#20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V
#21 = Utf8 HelloWorld
#22 = Utf8 java/lang/Object
#23 = Utf8 java/lang/System
#24 = Utf8 out
#25 = Utf8 Ljava/io/PrintStream;
#26 = Utf8 java/io/PrintStream
#27 = Utf8 println
#28 = Utf8 (Ljava/lang/String;)V
让我们来查看主函数并理解Hello World的显示流程。
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello World!
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
首先,我们来看getstatic指令,它引用了#2。这表示我们正在获取字段#2,即java/lang/System.out的值,它是一个PrintStream类型的字段。
下面是LDC指令,它在运行时从常量池加载常量值。
#3 = String #18 // 你好,世界!
#18 = Utf8 你好,世界!
在这里加载了字符串“你好,世界!”
然后,使用invokevirtual指令调用。
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
将之前的字符串作为参数来执行println函数。
最后返回”void”并结束。
辛苦了,现在已经成功显示”Hello World!”。
总结
我在开始认真学习Java时,努力以我想知道的内容为重点,但是要简洁又能抓住要点的写作确实很难。我真的觉得将近一年前的我会想读这样的内容吗?
话虽如此,如果这篇文章对某人有帮助,我会感到幸运。如果你能因此对Java基础产生兴趣,那将是最好的。我决定好好学习Java基础,以便能继续以这样的方式分享。
如果有任何错误,请务必指出。非常感谢。