作者选择了 自由和开源基金作为 写给捐款计划的一部分接受捐款。
介绍
[Conditional statements](https://en.wikipedia.org/wiki/Conditional_(computer_programming) 更改程序流程. 条件声明也被称为 branching statements,因为当条件匹配时,流程会以一种方式进入代码的一个分支。如果一个条件不满足,则会评估另一个条件(如果有)。 此评估将继续进行,直到所有条件被评估为真
或假
。 例如,你可以将两个数字(x
和y
)与以下条件声明进行比较:x
> y,
x = y和
x < y。 如果
x等于
1和
y等于
2,则将有三个评估,直到最终的
x < y
条件声明被评估为真
。
有两种类型的条件。第一种类型是如果
和其扩展的else如果
变异。这种类型被广泛使用。第二种类型是交换机
,更具具体性和有限性。
在本教程中,您将在Java中写有条件的陈述,并了解每个类型的用例、好处和缺点。
前提条件
要遵循本教程,您将需要:
要在本地机器上设置,你需要以下内容:
- Java(版本 11 或更高)安装在你的机器上,由 Java 开发工具包 (JDK)提供的编译器。对于 Ubuntu 和 Debian,按照我们教程中的 选项 1的步骤来编译和运行代码,本教程使用 Java Shell,这是一个 Read-Evaluate-Print Loop_RE](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)从命令行运行的其他操作系统,包括 Mac 和 Windows。 要开始使用 JShell,请检查 [Introduction to JShell___Mell] 类型,本教程使用 Java Shell,这是我们对 Java 项目的理解,
](https://andsky.com/tech/tutorials/理解数据类型-在雅瓦瓦)。
声明和块之间的区别
当满足条件语句并将执行流向相应的代码分支时,该分支可能是单个语句或代码块。
一个 statement 是单个执行单位,通常在一个行上,用半色符号结束,例如,使用下面的陈述来打印例子
:
1System.out.println("example");
<$>[info]
信息: 要跟进本教程中的示例代码,请在本地系统上运行jshell
命令,打开Java Shell工具,然后您可以复制、粘贴或编辑示例,在jshell>
提示后添加它们并按ENTER
。
此语句使用方法 println()
来打印一个字符串,在这种情况下是 example
. 除非另有指示,Java 将无条件地执行此语句。
<$>[注] 注: 陈述通常写在一行上,以便使其更易于阅读。然而,根据 官方公约指南,你应该避免长于80个字符的行。
此外,在某些情况下,例如在lambdas中,将陈述分布在几个行上更为方便和直观,无论如何,Java在陈述中不会对新行提出语法要求,您可以简单地在新行上继续陈述。
当你组合陈述以便它们一起执行时,你正在使用一个块。 block 是一个包含零或更多陈述的组合,从一个开头条({
)开始,并以一个关闭条(}
)结束。
1{
2 System.out.println("example");
3}
在上面的区块中,你已经使用了四个空间,而在System.out.println
(例子
);`这四个空间被称为 indentation。 与其他编程语言(如 Python)不同,Java 中的插入不需要,也不会影响代码。 然而,为了更好的读取性,并且根据 公约,一个区块内的行从四个插入开始。 大多数代码编辑器都支持自动插入,但在编程语言和编辑器之间也不同,因此,如果您的代码编辑器支持插入,请确保在编写Java 代码时设置为四个插入。
在这种情况下,将代码放置在一个块内没有区别,因为没有条件。因此,示例
将被打印,无论声明是否在一个块内。
1[secondary_label Output]
2example
上面的输出表明,用于打印示例
的声明从块内部和外部相同的方式工作。
在本节中,您了解了陈述,块,以及如何创建它们。在下一节中,您将向代码块添加一个条件陈述。
单一如果条件使用
最常用的条件陈述是如果
陈述. 它是普遍的,适合任何需要的条件比较,只要比较的结果是布尔式(真
或假
) 。
单个如果
语句用于在单一条件下执行一个代码片段. 你会将条件执行代码放入块中,并在开始时放入如果(布尔式表达式)
。
在本示例中,您将写一个代码片段,比较两个数字。 根据比较的结果,可能会打印一个消息。
1int x = 1;
2int y = 0;
3if (x > y) {
4 System.out.println(x + " is bigger than " + y);
5}
你在前两行中定义了两个变量:x
和y
。第三行是如果(x > y)
的条件,它比较了x
是否大于y
。
区块代码始于第一个开关轴({
)并以关闭轴(}
)结束。区块内部,一个陈述使用println()
方法来打印x
大于y。
当你在jshell中运行此代码时,你会得到以下输出:
1[secondary_label Output]
2x ==> 1
3y ==> 0
41 is bigger than 0
输出的前两行确认了x
和y
的值,第三行读到1大于0
,这意味着条件声明是true
:x
大于y
。
条件陈述中最重要的规则是,评估的表达式必须评估为boolean
,在任何其他情况下,您将收到一个错误,即您所比较的表达式不能转换为boolean
。
若要进行额外的练习,请尝试使用非布尔式表达式造成错误. 要做到这一点,请将不能转换为布尔式
的int
变量放入以下条件列中:
1int x = 1;
2if (x) {
3 System.out.println("Will this work?");
4}
在第 1 行中,您定义了 int
变量 x
,并为其分配一个值 1
。第 2 行是 if (x)
的条件,这会导致程序崩溃,因为 `x' 无法转换为布尔语。
1[secondary_label Output]
2x ==> 1
3| Error:
4| incompatible types: int cannot be converted to boolean
5| if (x) {
6| ^
接下来的行描述了关于不相容类型
的错误,并解释了像x
这样的int
值不能转换为boolean
值。
像这样的非布尔条件声明可能是条件声明中最常见的陷阱。幸运的是,现代IDEs(集成开发环境)在你写作时会捕捉到这样的错误。
写有条件的如果没有块的陈述
Java的如果
条件的一个特征是,有更短的方式来写它们而不使用代码块.虽然不推荐使用代码块的条件,你应该知道这样写代码是可能的。
例如,而不是使用一个代码块,你可以写这样一个陈述:
1int x = 1;
2int y = 0;
3if (x > y)
4 System.out.println(x + " is bigger than " + y);
与上一个示例的区别在于,如果(x > y)的条件语句之后没有代码块,相反,目标语句System.out.println(x +
大于 + y
)即将在条件语句
if (x > y)`之后。
当您在jshell
中运行此时,您将获得与上一个示例相同的输出:
1[secondary_label Output]
2x ==> 1
3y ==> 0
41 is bigger than 0
x
和y
的值将打印在前两行上,并在第3行上打印1大于0
的确认信息。
当没有条件代码之后的区块代码时,只有条件代码之后的直线取决于条件代码。在这种情况下,在条件代码之后的任何陈述都会被执行,不论条件代码如何。
1int x = 0;
2int y = 0;
3if (x > y)
4 System.out.println(x + " is bigger than " + y);
5 System.out.println("This line is always printed.");
当你在jshell中运行上述代码时,你会得到以下输出:
1[secondary_label Output]
2x ==> 0
3y ==> 0
4This line is always printed.
x
和y
的值打印在1行和2行上。这两个值都是0
,这意味着它们是平等的。 因此,条件声明x > y
返回错误。 因此,第四行说x大于y
并未打印。 但是,第5行被打印,因为其执行不取决于条件声明。
此外,第 5 行上的注释是不必要的。 它被列入,以暗示第 5 行的执行取决于条件,而不是这种情况。
使用无代码块的条件语并不直观或易于遵循,这就是为什么您应该谨慎地使用短语法。为了保持代码清洁和易于理解,最好使用区块语句,因为它们更易于阅读,并允许您拥有多个条件执行代码行。
嵌入式如果
语句是另一个可以编写代码的例子,但通常不推荐,在下一节中,您将探索嵌入式如果
语句,以更好地了解它们的价值和缺点。
假如声明
要创建一个更复杂的条件结构,可以组合多个如果
陈述. 要创建嵌入式如果
陈述,您可以将另一个如果
陈述放置在母体如果
陈述中,而不是在代码块中。
这种做法通常不建议,因为它使您的代码更难阅读和理解,但是,如果陈述有时有实际用途,所以熟悉它们是有帮助的。
要了解如何做到这一点,您将通过添加另一个如果
语句来扩展上一个示例,您将再次比较y
来评估它是否等于0
。
1int x = 1;
2int y = 0;
3if (x > y) {
4 if (y == 0) {
5 System.out.println("This is legal but does not look clean.");
6 }
7}
前三行从前面的例子中保持不变:你定义两个int
变量(x
和y
)并比较它们。在第4行,另一个if
声明比较y
是否等于0
。
当你在jshell
中运行此操作时,你会得到以下输出:
1[secondary_label Output]
2x ==> 1
3y ==> 0
4This is legal but does not look clean.
第一两个行确认了x
和y
的值,第3行读到这是合法的,但看起来不干净
这个消息确认了区块代码已经执行,因为如果
条件都满足了:x > y
和y == 0
。
但是,每次嵌入的如果
语句,你会增加代码的复杂性并降低其可读性,这就是为什么嵌入如果
语句通常不被认为是好的编码实践。
然而,嵌套的条件结构确实有某些实际用途。有时,似乎值得牺牲可读性和增加复杂性,以便编写更短的代码,并有可能节省时间。
使用与其他如果和其他陈述的延长如果条件
可以进一步扩展如果
条件来处理附加匹配标准,使用else if
和else
补充声明。else
声明只能在最初的如果
声明之后使用。在else if
下,可以添加无限的附加条件声明,类似于第一个如果
。
通过else if
和else
,你可以将你的程序流向分支到更多的方向,而不是单个if
。因此,你可以构建复杂的条件结构,无法以任何其他方式构建。
开始使用以下代码示例以获取else if
和else
语句的想法. 您将扩展以前使用的代码并添加更多的条件分支。
1int x = 1;
2int y = 0;
3if (x > y) {
4 System.out.println(x + " is bigger than " + y);
5} else if (x < y) {
6 System.out.println(y + " is bigger than " + x);
7} else if (x == y) {
8 System.out.println(x + " is equal to " + y);
9} else {
10 System.out.println(x + " cannot be compared to " + y);
11}
根据上面的代码,第1和2行定义了两个变量(‘x’和‘y’)的值为‘1’和‘0’。在第3和4行中,您将评估‘x’是否比‘y’大,以一个‘if’陈述。如果评估是‘true’,则将打印出‘x’大于‘y’的文本,并且将退出条件结构。如果评估是‘false’,程序将继续到下一个条件。
在第5行,在如果
声明的关闭栏后,出现一个else if
声明. 它具有与如果
类似的语法:在关节中有一个布尔式表达式和一个接下来的代码块。 该表达式评估了y
是否大于x
,这是前面的如果
声明的对立点。 如果该表达式是真
,则将执行随后的代码块,并且再次将退出条件结构。 在这种情况下,这是第6行上的声明,将打印y大于x
。
在第7行是另一个else if
案例. 此时,你检查x
是否等于y
在窗口中. 如果true
,8行上的陈述将被执行,它将打印x等于y
。
在第9行出现最后的else
声明. 它总是最终的,没有条件,这意味着它的分支总是输入,如果没有其他条件声明被匹配. 换句话说,在没有如果
或如果
条件之前已经满足时执行else
后的代码块。
如果您想要进行额外的比较,您可以有零或更多的else if
陈述. 最后,您可以放置一个可选的else
匹配,如果没有其他条件匹配。
当你在jshell中运行上述代码时,你会得到以下输出:
1[secondary_label Output]
2x ==> 1
3y ==> 0
41 is bigger than 0
上面的输出的第一行和第二行确认了x
和y
的值:1
和0
。第三行打印了1大于0
,这确认了布尔式表达式(x > y)
返回了真,并且在执行后,区块代码。
写如果
、else如果
和else
语句是写复杂的条件结构的好方法,因为你可以在每个如果
和else如果
语句中放置不同的条件。
但是,如果您需要进行更多的比较,则添加更多的else if
陈述会使代码难以遵循,甚至令人困惑,这就是为什么您应该在可能的情况下使结构小而简单。
使用 switch 条件
交换
语句是你可以用来构建决策结构的另一个有条件的语句,它类似于如果
语句,因为它可以被用来条件定制程序流程,但是,交换
语句与单个变量工作,并与不同的预定义案例匹配。因此,你不能评估诸如x > y
这样的布尔语表达式。相反,你可以有一个int
变量,并与其他int
变量匹配它的值;当有匹配(即case
),程序流程将根据匹配进行重定向。
第一个是比较变量只能是特定数据类型,如原始类型int
和char
,以及参考类型String
和Integer
。(支持的数据类型的完整列表可以在官方switch
文档中找到)。
另一个重要的规则是案例
陈述的值必须是 literals或 constants. Constants类似于变量,但它们在定义时前面有关键字final
。
交换机
比如果
结构更有限,它不是一个完整的替代品,但它具有更易读的独特优势,并且在可行的情况下更适合更多的比较。
例如,想象一下,你想将每个月的数值( 1 到 12 )与月的名称匹配。 使用一个如果
- else if
结构,你需要做十二个相似的比较。
要练习使用这个例子中的交换
条件语法,请将下列行添加到jshell
。
1int monthOfYear = 1;
2switch (monthOfYear) {
3case 1:
4 System.out.println("January");
5 break;
6case 2:
7 System.out.println("February");
8 break;
9default:
10 System.out.println("Not a month");
11}
在第 1 行中,有一个变量monthOfYear
的值为1
。这个变量将用于交换
陈述。在第 2 行中,出现了交换
陈述的定义。变量monthOfYear
被放置在窗口中,以表明它将被比较。
在第三行出现了第一个案例
值为1
。第一个比较将是monthOfYear
是否等于1
。一个(:
)总是跟随比较值。在第四行出现了println()
方法来打印,如果1
匹配,它应该打印1月
作为月的名称。
在第一个案例之后,在第5行出现一个破
声明,这导致交换机
条件结构在满足条件时退出。因此,一旦破
被执行,不会有其他案例
条件进行评估。相反,程序流程将在交换机
条件结构的关闭后继续运行,这在本示例中的第11行。 注意破
是可选的,你可能会忘记包括它。 在这种情况下,交换机
将继续评估剩余的案例,而不是在有匹配时退出条件结构。
下一个案例
条件是6、7和8行,这将匹配月年
值是否为2
。这三个行跟前三行相同的语法,但在7行中有一个新的二月
字符串,简而言之,剩余10个月的案例
条件被省略了。
在第9行是默认
陈述. 它没有条件,因此它总是匹配. 它是可选的,并且用于定义程序流的默认路径,当没有之前列出的案例匹配时。
在第 11 行中,有一个关闭轴,以终止条件语句的代码块。
要执行上述代码,请将其粘贴到jshell
中,您将收到以下输出:
1[secondary_label Output]
2monthOfYear ==> 1
3January
第一行确认月OfYear
的值为1
。第二行打印1月
,这意味着对应了1
值的案例
条件:月OfYear
是1
,从而触发下一行打印1月
的声明。
作为一个练习,尝试改变monthOfYear
的值,添加更多的案例
条件,甚至删除破
陈述,以了解结果将如何改变。
结论
在本教程中,您使用了条件声明来指导执行流程. 您了解了什么时候使用如果
和交换
声明是合适的,并写了一些代码示例,您还了解了清洁代码的最佳实践以及如何避免与条件相关的常见陷阱。
關於Java的更多信息,請參閱我們的 如何在Java中編碼系列。