购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

bt2-L 1.1 我们的第一个程序

当学习任何新的编程语言时,传统做法是从一个能够显示“Hello, World!”消息的程序开始,这也是在下面的小节中我们将要做的事情。

1.1.1 剖析“Hello, World”程序

话不多说,下面就是Java中的“Hello, world”程序。

package ch01.sec01;
 
// Our first Java program 
 
public class HelloWorld {
     public static void main(String[] args) {
          System.out.println("Hello, World!");
     }
}

让我们一起来看看这个程序。

Java是一种面向对象的语言。在程序中,通常需要控制 对象 (object)来让它们完成具体工作。操作的每个对象都属于特定的 (class),通常也称这个对象是该类的一个 实例 (instance)。类定义了对象的状态是什么,以及对象能做什么。在Java中,所有代码都是在类中定义的。第2章将详细介绍对象和类。这个程序是由一个名为HelloWorld的单一类组成的。

main是一个 方法 (method),也就是在类中声明的一个函数。main方法是程序运行时调用的第一个方法。main方法声明为static,以表示该方法不作用于任何对象。(当调用main方法时,只有少数的预定义对象,并且它们都不是HelloWorld类的实例。)main方法也声明为void,以表示它不返回任何值。关于main方法中参数声明String[ ] args的含义,参见1.8.8小节。

在Java中,你可以将许多特性声明为public或private。除此之外,Java中还有一些其他可见性级别。这里将HelloWorld类和main方法都声明为public,这是类和方法中最常见的定义形式。

包( package 是一组相关类的集合。把相关类放在一个包中是一个很好的做法,这样可以将相关类组合在一起,并避免多个类在具有相同名称时可能会发生的冲突。本书使用章(Chapter)和节(Section)的编号作为包名。因此,示例中类的全名就是ch01.sec01.Helloworld。第2章会有更多关于包和包命名规范的内容。

以 // 开头的行是注释。编译器会忽略从 // 到行末的所有字符,这些字符仅仅用来辅助编程人员阅读程序。

最后,来看看main方法的主体。在示例中,它由一行命令组成,该命令的功能是向System.out输出一个消息,System.out对象代表Java程序的“标准输出”。

正如你所见,Java不是一种可以用来快速执行一些简单命令的脚本语言。它的类、包和模块(模块在第15章中介绍)等特性使得它更适合用于编写大型程序。

Java也非常简单和统一。一些编程语言不仅有全局变量和全局函数,还有类内部的变量和方法。在Java中,所有东西都在类中声明,这种统一性可能会导致代码有些冗长,但也使得理解程序的含义变得容易。

注意: 你刚刚看到了一个 // 形式的注释,它的注释效果是延伸到行末的。还可以在 /* 和 */ 分隔符之间添加多行注释。例如:

/*
    This is the first sample program in Core Java for the Impatient.
    The program displays the traditional greeting "Hello, World!".
*/

还有第三种注释样式,称为 文档注释 (documentation comment),使用/** 和 */作为分隔符。下一章中将会介绍。

1.1.2 编译和运行Java程序

要编译和运行一个Java程序,需要安装Java开发工具包(Java Development Kit,JDK),此外,也可以安装集成开发环境(Integrated Development Enviroment,IDE)。可以在异步社区中下载本书的示例代码。

一旦安装了JDK,就可以打开一个终端窗口,并切换到包含ch01目录的目录,然后运行以下命令:

javac ch01/sec01/HelloWorld.java 
java ch01.sec01.HelloWorld

然后,那条熟悉的问候语就将出现在终端窗口中,如图1-1所示。

图1-1 在控制台窗口运行Java程序

需要注意的是,执行程序需要两个步骤。首先,javac命令将Java源代码 编译 (compile)成一个与机器无关的中间表示,称为 字节码 (byte code),并将它们保存在 类文件 (class file)中;然后,java命令启动一个 虚拟机( virtual machine ,该虚拟机会加载类文件并执行编译后的字节码。

一旦编译完成,字节码可以在任意一个Java虚拟机中运行,无论是在你的台式计算机上或者是在遥远银河系中的某个设备上。这个“一次编写,处处运行”的承诺是Java的一个重要设计标准。

注意: javac编译器是通过文件名进行调用的,使用斜杠分隔文件路径段,文件扩展名为.java。java虚拟机的启动器是通过类名进行调用的,使用点号来分隔包的名称段,并且没有扩展名。

注意: 如果程序由单个源文件组成,那么可以跳过编译的步骤,直接使用以下命令运行程序:

java ch01/sec01/HelloWorld.java

在后台,程序将会在运行之前进行编译,但不会生成类文件。

注意: 在类Unix操作系统上,你可以按照以下步骤将Java文件转换为可执行程序。

(1)重命名文件,删除其扩展名.java。

mv HelloWorld.java hello

(2)使文件可执行。

chmod +x hello

(3)在文件顶部添加一行bash的运行标记。

#!/path/to/jdk/bin/java --source 17

现在,你就可以通过以下方式运行程序了。

./hello

如果要在IDE中运行程序,首先需要按照IDE安装说明中描述的方式创建一个项目。然后,选择HelloWorld类并通过IDE运行它。图1-2显示了程序在Eclipse中的运行情况。Eclipse是一个非常流行的IDE。除此之外,还可以选择许多其他优秀的IDE。随着对Java编程的不断学习和深入了解,还是应该多尝试几种IDE,再从中选择一个自己喜欢的。

图1-2 在Eclipse IDE中运行Java程序

好了,恭喜你刚刚完成了使用Java运行“Hello,World!”程序这一古老的传统,下面我们就准备开始学习Java语言的基础知识。

提示: 在异步社区官网中可以下载本书所有章节的示例代码。这些代码经过精心编排和组织,你可以很方便地创建一个包含所有示例程序的单个项目。建议你在仔细阅读本书中内容的同时,下载、运行和学习这些配套代码。

1.1.3 方法调用

让我们更仔细地看看main方法中唯一的语句:

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

System.out是一个对象,它是一个名为PrintStream的类的 实例( instance 。PrintStream类有println、print等方法。这些方法被称为 实例方法 (instance method),因为它们对类的对象或实例进行操作。

若要在对象上调用实例方法,请使用 点符号 (dot notation)来表示:

object.methodName(arguments)

在这个例子中,main方法只有一个参数,即字符串"Hello, World!"。

让我们用另一个例子来试试,像"Hello, World!" 这样的字符串是String类的实例。String类有一个返回String对象长度的length方法。若要调用该方法,则需要再次使用点符号:

"Hello, World!".length()

length方法是通过对象"Hello, World!"调用的,且该方法没有参数。与println方法不同,length方法会返回一个结果。使用该返回结果的一种方法就是将它输出到屏幕:

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

一起来试试看。用这个语句来编写一个Java程序并运行它,看看字符串的长度是多少。

在Java中,需要自己 构造 (construct)大多数对象(不像System.out和"Hello, World!"这些对象,它们是已经存在的,可以直接使用)。下面是一个简单的示例。

Random类的对象可以生成随机数。可以使用new运算符来构造一个Random对象:

new Random()

在类名之后的是构造参数列表,在这个例子中该列表是空的。

你可以在构造的对象上调用方法。例如:

new Random().nextInt()

这样就可以通过这个新构造的随机数生成器,生成下一个随机整数。

如果想在一个对象上调用多个方法,那么需要将对象存储在变量中(参见1.3节)。这里我们打印两个随机数:

Random generator = new Random(); 
System.out.println(generator.nextInt()); 
System.out.println(generator.nextInt());

注意: Random类是在java.util包中声明的。为了在程序中使用这个类,需要添加import语句,示例如下。

package ch01.sec01; 
 
import java.util.Random; 
 
public class MethodDemo {
    ...
}

我们将在第2章中更详细地了解包和import语句。

1.1.4 JShell

在1.1.2小节中,你看到了如何编译和运行一个Java程序。JShell程序提供了一个“读取—评估—打印循环”(read-evaluate-print loop,REPL)的方式,它允许你尝试Java代码而无须编译和运行程序。当输入Java表达式时,JShell会评估输入,并打印结果,然后等待下一次输入。如果要启动JShell,只须在终端窗口中输入jshell,如图1-3所示。

图1-3 运行JShell

JShell以问候语开头,然后显示提示符:

|  Welcome to JShell -- Version 17
|  For an introduction type: /help intro
 
jshell>

现在可以输入一个Java表达式,例如:

"Hello, World!".length()

JShell会给你一个反馈,表示运行结果和下一个提示符:

$1 ==> 13
 
jshell>

需要注意的是,你并 没有 输入System.out.println。JShell会自动打印输入的每个表达式的值。

输出中的$1表示该结果可用于进一步的计算。例如,如果继续输入:

3 * $1 + 3

则JShell的反馈为:

$2 ==> 42

如果需要多次使用一个变量,那么可以给它指定一个更加容易记忆的名字。一定要遵循Java语法,同时指定类型和变量名(参见1.3节)。例如:

jshell> int answer = 42 
answer ==> 42

可以让JShell替你填写类型。具体操作是,输入一个表达式,不要按Enter键,而是按住Shift+Tab组合键,然后按V键。例如,当输入:

new Random()

然后按Shift + Tab组合键和V键,你会看到:

jshell> Random = new Random()

这时的光标位于 = 符号之前。此时可以输入一个变量名,然后按Enter键:

jshell> Random generator = new Random() 
generator ==> java.util.Random@3fee9989

此外,还有一个很棒的功能是Tab补全功能,例如输入:

generator.

随后按Tab键,你将会得到一个可以在generator变量上调用的所有方法的列表:

jshell > generator.
doubles(                   equals(                 getClass()         
hashCode()                 ints(                   isDeprecated()
longs(                     nextBoolean()           nextBytes(          
nextDouble(                nextExponential()       nextFloat(
nextGaussian(              nextInt(                nextLong(           
notify()                   notifyAll()             setSeed(
toString()                 wait(

现在输入ne再按Tab键。方法名会补全为next,并且你会得到一个更加简短的列表:

jshell> gengerator.next
nextBoolean()              nextBytes(              nextDouble(         
nextExponential()          nextFloat(              nextGaussian(
nextInt(                   nextLong(

如果再按D键和Tab键,方法名会自动补全为nextDouble(。再次按Tab键,将会看见3个备选:

Signatures:
double java.util.random.RandomGenerator.nextDouble(double bound)
double java.util.random.RandomGenerator.nextDouble(double origin, double bound) 
double Random.nextDouble()
  <press tab again to see documentation>

按)键可以选择第3个版本:

jshell> gengerator.nextDouble()
$3 ==> 0.9560346568377398

注意: 在自动完成列表中,需要参数的方法只能后跟左括号,如nextDouble(,而不需要参数的方法有一对完整括号,如nextBoolean()。

如果要重复运行命令,可以按 ↑ 键,直到看到要重新运行或编辑的行。可以用 ← 键和 → 键移动命令行中的光标,并添加或删除字符,完成后按Enter键。例如,按 ↑ 键并用Int替换Double,然后按Enter键:

jshell> generator.nextInt()
$4 ==> -352355569

默认情况下,JShell将会导入以下包:

java.io
java.math
java.net
java.nio.file 
java.util
java.util.concurrent 
java.util.function 
java.util.prefs 
java.util.regex 
java.util.stream

这就是可以在JShell中使用Random类而不需要任何导入语句的原因。如果需要导入其他类,可以在JShell提示符下输入导入语句。或者,更方便的是,通过按住Shift+Tab组合键和I键,可以让JShell搜索它。例如,输入Duration,然后按住Shift+Tab组合键和I键,你将获得一个潜在操作的列表:

jshell> Duration
0: Do nothing
1: import: java.time.Duration
2: import: javafx.util.Duration
3: import: javax.xml.datatype.Duration 
Choice:

输入1,然后你将收到一个确认信息:

Imported: java.time.Duration

随后显示:

jshell> Duration

这样就完成了导入工作,然后就可以继续工作了。这些命令足以让你开始使用JShell。要获得更加详细的帮助,输入/help并按Enter键。如果要退出JShell环境,输入/exit并按Enter键,或者只须按Ctrl+D组合键。

JShell使得Java语言和相关库的学习变得轻松而有趣,且无须启用庞大的开发环境和编写复杂的public static void main等代码。 PD8bi9QR5eAGJwxIyUJ4y1IFKndQDfvgDFE7Bxl/jO2+v5T9s9p+9dvahGi7o3dh

点击中间区域
呼出菜单
上一章
目录
下一章
×