第 7 课:表达式

本文介绍了JavaFXScript中的各种表达式类型,包括块、if、范围、for和while表达式等。通过实例展示了如何使用这些表达式进行逻辑控制和数据处理。

 第 7 课:表达式

表达式是可以生成某个结果值的代码段,可以结合使用表达式来生成“更大的”表达式。JavaFX Script 编程语言是表达式语言,这意味着一切(包括循环、条件甚至块)都是表达式。在某些情况下(如 while 表达式),表达式具有 Void 类型,这意味着它们不返回结果值。
 

目录


块表达式
if 表达式
范围表达式
for 表达式
while 表达式
break 和 continue 表达式
throw、try、catch 和 finally 表达式
 

块表达式由一系列声明或表达式组成,它们括在花括号中并用分号进行分隔。块表达式的值是最后一个表达式的值。如果块表达式中不包含表达式,则其类型为 Void。请注意,vardef 是表达式。

下面的块表达式对几个数字进行相加并将结果存储在一个名为 total 的变量中:

var nums = [5, 7, 3, 9];
var total = {
var sum = 0;
for (a in nums) { sum += a };
sum;
}
println("Total is {total}.");
 

运行此脚本将生成以下输出:

Total is 24.
 

第一行 (var nums = [5, 7, 3, 9];) 声明一个整数序列。

第二行声明一个名为 total 的变量,该变量将用来存放这些整数的和。

随后的块表达式由左花括号和右花括号之间的所有内容构成:

{
var sum = 0;
for (a in nums) { sum += a };
sum;
}
 

在该块内部,第一行代码声明一个名为 sum 的变量,该变量将用来存放此序列中各个数字之和。第二行(一个 for 表达式)遍历该序列,将每个数字与 sum 相加。最后一行设置该块表达式的返回值(在本例中为 24)。

使用 if 表达式后,仅当特定条件为真时才执行某些代码块,从而对程序流进行定向。

例如,以下脚本基于年龄来设置票价。12 岁到 65 岁的人支付正常价 10 美元。老人和儿童支付 5 美元;5 岁以下的儿童免费。

def age = 8;
var ticketPrice;

if (age < 5 ) {
ticketPrice = 0;
} else if (age < 12 or age > 65) {
ticketPrice = 5;
} else {
ticketPrice = 10;
}
println("Age: {age} Ticket Price: {ticketPrice} dollars.");
 

如果将 age 设置为 8,该脚本将生成以下输出:

Age: 8 Ticket Price: 5 dollars.
 

该示例的程序流如下所示:

if (age < 5 ) {
ticketPrice = 0;
}
else if (age < 12 or age > 65) {
ticketPrice = 5;
} else {
ticketPrice = 10;
}
 

如果 age 小于 5,则票价将设置为 0。

程序随后将跳过其余条件测试并输出结果。

如果 age 不小于 5,程序将继续执行下一个条件测试(由后跟另一个 if 表达式的 else 关键字来指示):

if (age < 5 ) {
ticketPrice = 0;
} else if (age < 12 or age > 65) {
ticketPrice = 5;
}
else {
ticketPrice = 10;
}
 

如果人的年龄在 5 到 12 岁之间或者大于 65 岁,该程序会将票价设置为 5 美元。

如果人的年龄在 12 到 65 岁之间,程序会流至最后一个代码块(用 else 关键字进行标记):

if (age < 5 ) {
ticketPrice = 0;
} else if (age < 12 or age > 65) {
ticketPrice = 5;
} else {
ticketPrice = 10;
}
 

只有当前面的所有条件均不满足时,才会执行此块。它会针对 12 到 65 岁之间的人将票价设置为 10 美元。


注:可以将上面的代码缩减成一个非常简洁的条件表达式:

ticketPrice = if (age < 5) 0 else if (age < 12 or age > 65) 5 else 10;
 
这是一个需要掌握的有用方法,在本教程的后面部分中还会使用它。

“序列”一课讲授了一种用来声明形成等差数列的数字序列的简化表示法。

var num = [0..5];
 

从技术上讲,[0..5] 是一个范围表达式。默认情况下,相邻值之间的间隔为 1,但是您可以使用 step 关键字来指定一个不同的间隔。例如,定义一个由 1 到 10 之间的奇数构成的序列:

var nums = [1..10 step 2];
println(nums);
 

此脚本的输出如下所示:

[ 1, 3, 5, 7, 9 ]
 

要创建降序范围,请确保第二个值小于第一个值,并指定一个负的 step 值:

var nums = [10..1 step -1];
println(nums);
 

输出为:

[ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
 

如果您在创建降序范围时没有提供负的 step 值,则会生成一个空序列。

以下代码:

var nums = [10..1 step 1];
println(nums);
 

将生成下面的编译时警告:

range.fx:1: warning: empty sequence range literal, probably not what you meant.
var nums = [10..1 step 1];
^
1 warning
 

如果您完全忽略 step 值,也会生成一个空序列。

另一个与序列有关的表达式是 for 表达式。for 表达式为遍历序列中的各个项提供了一种方便的机制。

以下代码提供了一个示例:

var days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];

for (day in days) {
println(day);
}
 

此脚本的输出如下所示:

Mon
Tue
Wed
Thu
Fri
Sat
Sun
 

让我们将该示例分成几个部分。for 表达式以 "for" 关键字开头:

for (day in days) {
println(day);
}
 

days 变量是要由 for 表达式处理的输入序列的名称:

for (day in days) {
println(day);
}
 

for 表达式遍历该序列时,day 变量用来存放当前项:

for (day in days) {
println(day);
}
 

请注意,不需要在脚本中的其他位置声明 day 变量即可将其用在 for 表达式中。此外,在完成整个循环之后,将无法访问 day。程序员通常会赋予临时变量(如该变量)非常短的名称(或由一个字母构成的名称)。

在上例中,未显示 for 返回值;但 for 也是一个返回序列的表达式。以下代码显示了两个使用 for 表达式从另一个序列创建序列的示例:

// Resulting sequence squares the values from the original sequence.
var squares = for (i in [1..10]) i*i;

// Resulting sequence is ["MON", "TUE", "WED", and so on...]
var capitalDays = for (day in days) day.toUpperCase();
 

请注意,toUpperCase 函数由 String 对象提供。您可以通过查阅 API 文档来查看完整的可用函数列表。

另一个循环结构是 while 表达式。与作用于序列中项的 for 表达式不同,while 表达式会一直循环,直到给定的表达式为 false 为止。尽管 while 在语法上是表达式,但是它的类型为 Void,不返回值。

下面提供了一个示例:

var count = 0;
while (count < 10) {
println("count == {count}");
count++;
}
 

此脚本的输出如下所示:

count == 0
count == 1
count == 2
count == 3
count == 4
count == 5
count == 6
count == 7
count == 8
count == 9
 

第一行声明一个名为 count 的变量并将其初始化为 0:

var count = 0;
while (count < 10) {
println("count == {count}");
count += 1;
}
 

第二行以 while 表达式开头。此表达式创建了一个循环(在左花括号和右花括号之间),该循环会一直进行,直到 count < 10 的值为 false 为止:

var count = 0;
while (count < 10) {
println("count == {count}");
count += 1;
}
 

While 表达式的主体会输出 count 的当前值,然后将 count 的值加 1:

var count = 0;
while (count < 10) {
println("count == {count}");
count += 1;

}
 

count 等于 10 时,循环退出。要创建一个无限循环,请将 true 关键字放在左小括号和右小括号之间,如 while(true){} 中所示。

breakcontinue 表达式与循环表达式有关。这两个表达式会影响循环迭代:break 完全放弃循环,而 continue 仅放弃当前迭代。

尽管 breakcontinue 在语法上是表达式,但它们的类型为 Void,不返回值。

示例:

for (i in [0..10]) {
if (i > 5) {
break;
}

if (i mod 2 == 0) {
continue;
}

println(i);
}
 

输出:

1
3
5
 

如果没有 if 表达式,该程序将只是输出 0 到 10 之间的数字。

如果只有第一个 if 表达式,程序将在 i 的值大于 5 时中断循环:

if (i > 5) {
break;
}
 

因此,程序将仅输出 1 到 5 之间的数字。

通过添加第二个 if 表达式,程序将仅放弃循环的当前迭代而继续执行下一个迭代:

if (i mod 2 == 0) {
continue;
}
 

在这种情况下,只有当 i 为偶数(即 i 能被 2 整除,没有余数)时才执行 continue。出现这种情况时,将永远不会调用 println(),因此输出中将不包含该数字。

在实际的应用程序中,正常的脚本执行流有时会被某个事件中止。例如,如果脚本从某个文件中读取输入,但是找不到该文件,该脚本将无法继续。我们将这种情况称为“异常”。


注意:异常是对象。它们的类型通常以它们所表示的情况命名(例如, FileNotFoundException 表示找不到文件的情况)。但是,定义一组特定于即将给出的示例的异常不在本节的讨论范围之内。因此,我们将使用一个通用的 Exception 对象(从 Java 编程语言借用而来)来说明 throwtrycatchfinally 表达式。

以下脚本定义(和调用)一个会抛出异常的函数:

import java.lang.Exception;

foo();

println("The script is now executing as expected... ");

function foo() {
var somethingWeird = false;

if(somethingWeird){
throw new Exception("Something weird just happened!");
} else {
println("We made it through the function.");
}
}
 

按原样运行此脚本(将 somethingWeird 设置为 false)将输出以下消息:

We made it through the function.
The script is now executing as expected...
 

但是,如果将该变量更改为 true,则会抛出异常。在运行时,该脚本将崩溃并显示以下消息:

Exception in thread "main" java.lang.Exception: Something weird just happened!
at exceptions.foo(exceptions.fx:10)
at exceptions.javafx$run$(exceptions.fx:3)
 

为了防止崩溃,我们将需要使用 try/catch 表达式来包装 foo() 调用。顾名思义,这些表达式尝试执行某些代码,但会在出现问题时捕捉异常:

try {
foo();
} catch (e: Exception) {
println("{e.getMessage()} (but we caught it)");
}
 

现在,程序不会崩溃,而只是输出:

Something weird just happened! (but we caught it)
The script is now executing as expected...
 

还有一个 finally 块(它在技术上不是表达式),无论是否抛出了异常,该块始终在 try 表达式退出之后的某个时间执行。finally 块用来执行无论 try 主体是成功还是抛出异常都需要执行的清除操作。

try {
foo();
} catch (e: Exception) {
println("{e.getMessage()} (but we caught it)");
} finally {
println("We are now in the finally expression...");
}
 

程序输出现在为:

Something weird just happened! (but we caught it)
We are now in the finally expression...
The script is now executing as expected...

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值