Java应用程序在语句的上下文中评估表达式,这些语句是独立的代码岛,完成各种任务,例如声明变量,做出决定或迭代语句。语句可以表示为简单语句或复合语句:
- 一个简单的语句是用于执行任务的一个独立的指令; 它必须用分号字符(
;
)终止。 - 一个复合语句是位于开放和近距离括号字符(之间的简单和其它复合语句序列
{
和}
),这限定了复合语句的边界。复合语句可以为空,将出现在简单语句的任何地方,或者称为块。复合语句不以分号结束。
在本文中,我将介绍您在Java程序中使用语句。你可以使用语句声明变量和指定表达式,做决定,迭代语句(是的,你可以使用语句迭代语句),断开和继续迭代,什么也不做。我将为未来的Java 101文章留下一些更加奇异的语句(如用于从被调用的方法返回值和抛出异常的语句)。
声明变量并将表达式指定为语句
在本系列的前面,我介绍了变量的概念,并提到变量必须在使用之前声明。我还提到一个变量声明最少包含一个类型名称,可选地后跟一对方括号对的序列,后跟一个名称,可选地后跟一对方括号对的序列,并以分号结束。此外,变量可以在其声明期间被显式初始化。
因为变量声明是一个独立的代码岛,它实际上是一个语句 - 一个简单的语句。这里有一些示例变量声明语句:
与变量声明语句紧密相关的是赋值语句,它为变量赋值(可能是对数组的引用或对对象的引用)。下面是几个例子:
赋值语句是一个的例子表达式语句,它是如果它随后用分号,可以使用作为语句的表达式。以下表达式也有资格作为表达式语句:
- 预增(例如,
++x;
) - 预处理(例如,
--y;
) - 后增量(例如
x++;
) - 后付款(例如
y--;
) - 方法调用(例如,
System.out.println("Hello");
) - 对象创建(例如,
new String("ABC");
)
做出决定
决策语句允许应用程序在多个执行路径之间进行选择。例如,如果销售人员本月销售的物品超过500件,则给销售人员一个奖金。此外,如果学生在代数测试中的成绩大于85%,则祝贺学生表现良好; 否则,建议学生更努力地学习下一个测试。
Java的支持if
,if
- else
和switch
决策声明。
if语句
最简单的Java决策语句是if
语句,它评估一个布尔表达式,并在该表达式的值为true时执行另一个语句。该if
语句的语法如下:
该if
声明与保留字开头if
,并用括号中的布尔表达式,这是后面的语句执行时,布尔表达式为true继续。
以下示例演示该if
语句。当age
变量包含值为55或更大时,if
执行System.out.println(...);
以输出消息:
许多人喜欢将任何简单语句if
包含在大括号中的语句后,有效地将其转换为等效的复合语句:
虽然大括号清楚了if
语句执行的内容,但我相信缩进提供了这种清晰度,并且大括号是不必要的。但是,您可能更喜欢指定大括号。
if-else语句
本if
- else
语句计算一个布尔表达式,当这个表达式的值为true执行一条语句,当计算结果为false执行另一个语句。以下是if
- else
语句的语法:
本if
- else
语句类似if
的语句,而且还包括保留字else
后跟一个语句时,布尔表达式为假的处理。
以下示例演示了一个if
- else
语句,告诉年龄小于55岁的人,直到提前退休的剩余时间:
条件运算符vs if-else
条件运算符(?:
)类似于if
- else
语句。但是,此运算符不能用于执行备用语句。相反,它只能返回同一类型的两个值之一。
链接if-else语句
Java允许您链多if
- else
陈述在一起,你需要选择多个语句执行的一个情况。生成的语法如下所示:
只要当前语句的布尔表达式求值为false ,链接就会执行后续的if
- else
语句if
。以下示例提供了此链接行为的演示:
第一if
- else
声明确定temperature
的价值为负。如果是,它执行System.out.println("freezing");
。如果不是,它执行第二if
- else
。
第二个if
- else
确定temperature
其值是否大于100.如果是,则执行System.out.println("boiling");
。否则,它执行System.out.println("normal");
。
悬而未决的问题
当if
和if
- else
一起使用时,和源代码是不正确的缩进,可能难以确定哪些if
与相关联else
。以下示例演示此问题:
在这个例子中,你可能期望看到x <= 0
输出。但这绝不会发生,相反没有什么会输出。该else
到其最近的比赛if
,这是if (y > 0)
。一旦这个例子重新格式化,你可以更清楚地看到发生了什么:
正如你所看到的,语句后面是一个if (y > 0) ... else ...
if
- 语句。要创建上一个示例的意图,您需要引入括号字符及其后续语句。基本上,一个块将遵循:else
if (x > 0)
if (y > 0)
if (x > 0)
因为x > 0
计算结果为false,System.out.println("x <= 0");
执行。该else
保留字匹配明确最多if (x > 0)
。
switch语句
该switch
声明让您从几个执行路径中更有效地比使用等效串连选择if
- else
报表。它具有以下语法:
该switch
语句从保留字开始,switch
并继续选择一个选择器表达式,该选择器表达式选择后续情况之一或默认情况执行。选择器表达式的计算结果为整数,字符或字符串。
开关和枚举常量
选择器表达式也可以求值为enum
常数。我将enum
在以后的文章中讨论。
每个案例标识要执行的语句。情况从保留字case
和标记大小写的值开始。以冒号(:
)字符是要执行的语句。该语句可以选择性地后跟break;
,将执行转移到第一个语句之后switch
。如果没有任何案例标签与选择器表达式的值匹配default
,则将执行以保留字开头的可选缺省案例。
以下示例演示了一个switch
语句,该语句确定整数值是偶数还是奇数(通过使用remainder运算符),然后通过其标签与其余部分匹配的大小写输出适当的消息:
此示例输出odd
,因为i % 2
产生1,其匹配第二个case标签。如果我省略break;
,如果数字是偶数,even
后面是odd
输出,因为执行将落到第二种情况。
断开您的交换机
忘记使用“ break;
” 结束案例是使用switch
语句时常见的错误。
有时,希望执行到下一个情况。例如,假设您要响应用户指定的大写或小写命令行选项字母,执行常用代码:
假设一个for
语句(稍后讨论)正在遍历传递给应用程序main()
方法的命令行参数数组中的每个参数。如果参数是-v
(破折号和小写字母v)或-V
(破折号和大写字母V),则会输出应用程序的版本号。当-v
指定时,有必要执行到以下情况,在指定时输出版本号-V
。
每当引用的字符串args[i]
与任何案例标签不匹配时,都会执行默认情况。换句话说,用户已经指定了未知选项。
链接if-else vs开关
有时,你可能需要一个链接之间进行选择if
- else
语句和等价switch
语句。你选择的声明应该提供最大的清晰度,对于手头的任务最少的冗长。
迭代语句
迭代语句(也称为循环语句)对特定数量的迭代(循环)或无限地重复执行其他语句,直到出现某些终止条件。例如,如前所述,您可能想要遍历String
传递给main()
方法的命令行参数数组中的所有对象。Java的支持for
,while
以及do
- while
循环语句。
for语句
该for
语句执行另一个语句的时间或无限期地一个具体的数字。它本质上是语句的紧凑形式while
(稍后讨论),并具有以下语法:
此语法显示for
语句从保留字开始,for
并以三个部分的括号分隔和分号分隔的序列继续:
-
initialize
:变量声明或赋值的逗号分隔列表。这些变量称为迭代变量或循环变量,用于索引数组,参与计算或执行其他任务。 -
test
:一个布尔表达式,决定循环执行的时间。只要此表达式保持真实,执行就会继续。 -
update
:通常修改循环变量的表达式的逗号分隔列表。
下面的for
语句是a statement
重复执行。
三个部分中的每一个是可选的。结果,for
可以缩小到for (; ;)
。因为没有停止条件,所以产生的循环被称为无限循环。
以下示例使用for
语句对名为数组的所有元素进行迭代args
,输出每个数组元素的值:
此示例工作如下:
- 声明变量
i
并将其初始化为0
。 - 评估
i < args.length
。如果i
相等args.length
,终止循环。 - 执行
System.out.println(args[i]);
。 - 执行
i++
。 - 继续执行步骤2。
变量i
对for
语句的test
和update
部分可见,并且对statement
。但是,对后续语句不可见。如果您希望后续语句查看i
最终值,请i
在之前声明for
,如下所示:
控制循环的变量可以是不同的基本类型,例如布尔,字符或双精度浮点。这里有三个例子:
最后,如前所述,该initialize
节可以声明多个变量。以下示例声明两个变量,在整个循环中递增一个变量并递减另一个变量:
输出由六行组成5
。
while语句
该while
语句重复执行另一个语句,而其控制布尔表达式保持求值为true。此语句具有以下语法:
此语法显示while
语句以保留字while
开头,并以括号布尔表达式继续。此语句后面是另一个重复执行的语句。
以下示例演示了while
语句:
此示例工作如下:
- 声明变量
i
并将其初始化为0
。 - 评估
i < args.length
。如果i
相等args.length
,终止循环。 - 执行
System.out.println(args[i]);
。 - 执行
i++
。 - 继续执行步骤2。
此示例while
等效于上一个for
示例。您可以压缩示例以重复执行简单语句,而不是复合语句,如下所示:
在这个压缩的示例中,我将postincrement语句更改为一个传递给数组索引运算符的表达式。虽然代码更紧凑,但为了清楚起见,您可能更喜欢前面的示例。
do-while语句
本do
- while
语句重复执行的声明,而其控制布尔表达式,执行语句之后进行评估,计算结果为true。此语句具有以下语法:
此语法显示一个do
- while
语句从保留字开始do
,继续使用一个重复执行的语句,并以保留字结束while
,后跟一个括号布尔表达式。
以下示例演示了do
- while
语句:
此示例工作如下:
- 声明
int
变量ch
以存储字符的数字代码。 - 提示用户按x键继续。
- 从键盘通过读取键代码
System.in.read()
,这是一个伴随的System.out.println()
。因为此方法将键的代码返回为int
,所以将此值赋给ch
。 - 比较
ch
的值与'x'
。注意,'x'
从比较之前char
到比较int
之前加宽。当此表达式的计算结果为false(ch
等于'x'
)时,终止循环。否则,请继续执行步骤2。
while
and do
- 之间的区别while
是while
执行其语句零次或多次,而do
- while
执行其语句一次或多次。您将基于此属性选择任一语句。例如,适合使用while
迭代args
数组,因为此数组可能长度为零,并且您不希望在这种情况下访问数组(并引发超出边界异常,这将在以后的文章中讨论) )。相反,您将使用do
- while
(和引发一个超出边界异常)访问数组至少一次。使用do
- while
提示用户输入密钥并读取响应是合适的,因为这些任务必须至少发生一次。
打破和继续迭代
您之前在break
语句的上下文中看到了switch
语句,用于switch
在案例执行后断开语句。然而,这个语句也可以在迭代语句上下文中使用,我将在本节中讨论。我也讨论了continue
语句,它只能在迭代语句上下文中使用。您将探索这些语句的未标记和已标记版本。
未标记的break和标记的break语句
无标签的break
声明终止switch
,for
,while
,或者do
- while
通过转移执行的第一条语句下面这句话的语句。它具有以下语法:
以下示例演示break
迭代语句上下文中的未标记语句:
此示例介绍了一个for
基于无限循环,重复提示用户按x键并读取此键,直到其等于'x'
。一个if
语句执行比较,执行break;
以在按x键时终止循环。
无限循环
你可以创建基于等效无限循环while
或do
- while
通过指定的语句true
作为布尔表达式(例如,while (true) ...
和do ... while (true);
)。虽然你通常想要避免无限循环,这通常是由错误的代码产生的 - 例如,创建一个循环的布尔表达式基于==
或!=
比较一个浮点变量的值和一个浮点值,不能在内存中精确表示为0.1) - 上面的示例显示了它们的一个用途。
标记的break
语句终止含有和标签switch
,for
,while
,或者do
- while
通过转移执行的第一条语句包含的语句下面的语句。它具有以下语法:
该语法包括保留字,break
后跟非保留字标识符作为标签,后跟分号。标签必须以前缀switch
或迭代语句为前缀,并且必须后跟冒号。
以下示例演示break
迭代语句上下文中的带标签语句:
这个例子呈现了一对嵌套的无限while
循环,它们描述了数字猜测游戏的一部分。外部循环是用于玩游戏的存根,而内部循环提示用户玩新游戏或退出游戏。
如果用户按下n键,break
则执行未标记语句以终止内循环,从而可以播放新游戏。如果q被按下,break outer;
则执行退出外部循环,其被分配outer:
标签。
未标记的continue和标签continue语句
未标记continue
语句跳过当前迭代的剩余部分,并指示迭代语句前进到下一次迭代。它具有以下语法:
下面是unlabeled continue
语句的使用示例:
这个例子的for
语句从迭代-2
到2
,重复执行一个if
- else
语句,然后i
在每次迭代后增加1。
为了防止i
包含0 的除零异常,if
测试i
0.如果是这种情况,它会执行continue;
,这导致for
增量i
然后求值i <= 2
。否则,10 / i
将求值并输出结果。
标记continue
语句跳过一个或多个嵌套迭代语句的剩余迭代,并将执行转移到标记的迭代语句。它具有以下语法:
该语法包括保留字,continue
后跟非保留字标识符作为标签,后跟分号。标签必须以前一个迭代语句为前缀,并且必须后跟冒号。
这里有一个使用labeled continue
语句的例子:
此示例呈现一对嵌套for
循环,每个循环变量范围从-2到2.其思想是将10除以循环变量值的乘积。然而,当任一变量包含0时,将除以零。
为了避免被零除链式if
- else
语句用于测试i
的和j
的为0。如果值i
的值为0,continue outer;
用来终止内部循环,推进外环(含标签outer:
)过去0.如果j
的值为0,continue;
用于退出当前内循环迭代并将内循环提前0.如果两种情况都不出现,则执行计算并输出其结果。
什么也不做
有一个最终语句要考虑,这是一个空语句,一个语句只包含分号字符。这个语句什么都不做,但它是有用的。请考虑以下示例:
此示例将标准输入流的内容(通过调用读取System.in.read()
)复制到标准输出流,通过调用写入System.out.print()
,System.out.println()
即不输出行分隔符的随播广告。它在标准输入流从键盘重定向到文本文件时效果最好。
当重定向到文件时,System.in.read()
当没有更多输入时返回-1。当不重定向时,System.in.read()
从键盘获取其输入,从不返回-1。相反,当没有更多的键代码返回时,System.in.read()
返回行分隔符字符 - 在Windows上需要两次调用以返回其\r\n
字符,Unix \ Linux上需要调用一次以返回其\n
字符,并且需要在旧的版本的Mac OS返回其\r
字符。欲了解更多信息,请换行符。
正如你可以看到的,所有的工作都在for
语句initialize
和test
节中执行。最后的分号是指空的语句,它被重复执行。
紧凑或不紧凑
一些开发人员会认为上一个示例是优雅的,因为它的紧凑性,而其他开发人员认为代码的紧凑性使其难以阅读和理解。你喜欢什么样式?
注意空语句,因为它可能是难以找到的错误的来源。例如,您可能希望以下语句for
输出该单词的10个实例Hello
:
相反,你将只观察这个单词的一个实例,因为for
语句的右括号后面有一个空语句。for
执行空语句10次,之后方法调用执行一次。
编写有趣的应用程序
现在,您已经探索了Java的所有基本语言功能,您已经准备好开始创建有趣的应用程序。例如,考虑一个随机选择从0到9的整数的猜测游戏,并要求您猜测此数字。如果你猜到太高或太低,游戏会告诉你。它也会告诉你,当你猜测,并会问你是否想再次播放。
在介绍游戏应用程序的源代码之前,我需要向您介绍这个源代码中尚未遇到的两个特性:
- 我使用
System.in.read()
返回按键的代码(当标准输入未重定向时)或文件中的8位值(当标准输入重定向时)。System.in.read()
能够抛出异常,所以我不得不附加“throws Exception
”到main()
方法头,如public static void main(String[] args) throws Exception
。这可以防止编译器报告错误。 - 要获得一个随机整数,我需要调用
random()
标准类库的Math
类的方法成员。random()
返回一个范围从0.0到几乎1.0的浮点值。表达式将此数字转换为更有用的整数。
清单1给出了应用程序的源代码Guess
。
清单1. Guess.java
Guess
展示了前面的文章中提出的几个陈述和其他基本特征。该main()
方法提供一个while
语句,生成一个新的数字,并给你一个机会去猜测它。表达(int) (Math.random() * 10)
乘以random()
10的返回值的范围内变化,以0.0至几乎10.0,并将结果转换为整数,从0到9的范围内。
需要括号
圆括号Math.random() * 10
是必要的,因为cast运算符[ (int)
]的优先级高于乘法(*
)。在没有圆括号的情况下,random()
返回值将被转换为整数,这将始终为0.将0乘以10将得到0,这将始终分配给number
。产生的游戏将是相当无聊。
生成数字后,main()
执行一个内部while
语句来处理所有的猜测。它反复提示猜测,将按下的键的Unicode字符值转换为从0到9的二进制整数值,并确定用户是否正确猜测。输出合适的消息。正确猜测的用户有机会通过按n
下来播放新游戏,或按下退出应用程序q
。
源代码的一个有趣的部分是while (System.in.read() != '\n');
。我使用这个语句\r\n
从操作系统的键盘缓冲区中刷新行分隔符(例如,在Windows上)。如果我不这样做,您将看到多个提示,因为每个分隔符字符将被解释为尝试输入从0到9(或n或q)的值。如果你在一个旧版本的Mac OS的运行Java,你可能不得不更换\n
用\r
,这是Mac的行分隔符。在Linux或Unix上运行时,无需进行任何更改,其行分隔符为\n
。(你可以通过使用标准类库的System
类来提供代码的可移植性,line.separator
我们将把这个任务作为未来的练习,当你对Java的类和方法更熟悉时)。
编译清单1如下:
然后运行应用程序:
以下是样品运行的输出:
结论是
语句是Java应用程序的主体。掌握它们与其他基本语言功能将帮助您开发一个坚实的基础,在其上建立您更高级的语言功能的知识。我们将在下一篇文章中开始这个扩展,在这篇文章中,我将向您介绍Java类和对象。