一、条件表达式
(一)语法格式
if (条件) 值1 else 值2
(二)执行情况
- 条件为真,结果是值1;条件为假,结果是值2。如果if和else的返回结果同为某种类型,那么条件表达式结果也是那种类型,否则就是Any类型
(三)案例演示
1、根据输入值的不同进行判断
- 也可以在一个表达式中进行多次判断
- 可以将上述条件表达式改造成嵌套的选择结构
2、编写Scala程序,判断奇偶性
- 打开Scala项目ScalaDemo2,创建net.fhl.structure包,在包里创建Example01对象
- 代码如下:
package net.fhl.structure
import scala.io.StdIn
object Example01 {
def main(args: Array[String]): Unit = {
print("n = ")
val n = StdIn.readLine().toInt
val res = if (n % 2 ==0){
n.toString + "是偶数"
}else{
n.toString + "是奇数"
}
println(res)
}
}
- 运行程序,查看结果
- 利用if结构具有返回值的特性,改写程序
- 运行程序,查看结果
二、块表达式
(一)语法格式
{语句组}
(二)执行情况
- 需要注意的是,Scala中的返回值是最后一条语句的执行结果,而不需要像Java一样单独写return关键字。如果表达式中没有执行结果,就返回一个Unit对象,类似Java中的void。
(三)案例演示
- 语句块最后一句的值就是整个块表达式的结果
- 语句块最后一句没有执行结果,那么块表达式结果就是Unit
三、for循环
(一)单重for循环
1、语法格式
for (变量 <- 集合或数组 (条件)) {
语句组
}
2、执行情况
- 表示将集合或数组中的每一个值循环赋给一个变量
3、案例演示
1、输出1到10
- 两种方式实现
- Range(a, b): 从a到b,不包含b,跟Python里的range函数一样,含头不含尾
- 1 to 10表示将1到10的所有值组成一个集合,且包括10。若不想包括10,则可使用关键字until
- 打印字符直角三角形
- 利用map函数产生每行星号构成的向量,然后利用foreach函数循环输出
- 利用双重循环与流间变量
2、遍历字符串,输出每个字符
- 方法一、按索引取字符串的每个字符
- 方法二:将字符串看作一个由多个字符组成的集合
3、计算 1 + 2 + 3 + … + 100
- 注意sum必须定义为var型变量
4、输出列表内的偶数
- 采用两种方式来实现
5、输出全部两位素数
for (n <- 10 to 100; if !(n % 2 == 0 || n % 3 == 0 || n % 5 == 0 || n % 7 == 0))
print(n.toString + " ")
(二)嵌套for循环
1、语法格式
- 传统格式
for (变量1 <- 集合或数组(条件))
for (变量2 <- 集合或数组(条件)) {
语句组
}
}
- 特有格式
for (变量1 <- 集合或数组; 变量2 <- 集合或数组 (条件)) {
语句组
}
2、案例演示
- 任务1、打印九九表
- 方法一、采用双重循环来实现
- 代码如下:
package net.fhl.structure
object Example02 {
def main(args: Array[String]): Unit = {
for (i <- 1 to 9) {
for (j <- 1 to i)
print(i.toString + "×" + j + "=" + (i * j) + "\t")
println()
}
}
}
- 运行程序,查看结果
- 方法二、采用单重循环来实现
- 在项目ScalaDemo2里创建Example03对象
- 代码如下:
package net.fhl.structure
object Example03 {
def main(args: Array[String]): Unit = {
for (i <- 1 to 9; j <- 1 to i) {
print(i.toString + "×" + j + "=" + (i * j) + "\t")
if (i == j) println()
}
}
}
- 运行程序,查看结果
- 方法三、采用单重循环与流间变量绑定来实现
- 在项目ScalaDemo2里创建Example04对象
- 在for循环头里sep = if (i == j) “\r\n” else "\t"就是流间变量绑定
- 代码如下:
package net.fhl.structure
object Example04 {
def main(args: Array[String]): Unit = {
for (i <- 1 to 9; j <- 1 to i; sep = if (i == j) "\r\n" else "\t")
print(i.toString + "×" + j + "=" + (i * j) + sep)
}
}
- 运行程序,查看结果
- 方法四、采用单重循环、流间变量与yield来实现
- for循环语句本身的返回值是Unit类型,无论在循环体中返回什么都是无效的,最终得到的都是Unit的值,但是可以在循环中的循环条件和循环体之间加上yield关键字,那么就可以将循环体产生的返回值组成数组进行返回。
- 在项目ScalaDemo2里创建Example05对象
- 代码如下:
package net.fhlstructure
//功能:采用单重循环、流间变量与yield打印九九表
object Example05 {
def main(args: Array[String]): Unit = {
val list = for (i <- 1 to 9; j <- 1 to i; sep = if (i == j) "\r\n" else "\t")
yield i.toString + "×" + j + "=" + (i * j) + sep
for (x <- list) print(x)
}
}
- 运行程序,查看结果
- 任务2、去掉对角线
- 方法一、传统双重循环
- 方法二、特有双重循环
四、条件循环
(一)while循环
1、语法格式
- Scala的while循环与Java类似
while(条件) {
循环体
}
2、案例演示
- 任务1、计算1+ 2 + 3 + … + 100
- 采用函数式风格来写代码,递归函数来实现求和
- 注意:sum必须是变量
- 任务2、打印全部水仙花数
- 所谓水仙花数,是指等于其各位数字立方和的三位数。
- 对于[100,
999]范围的每个数n,我们要去判断它是否等于其各位数字的立方和,这里的难点或关键在于如何分解一个三位数,得到它的每位数字。 - 假设我们已经把三位数n分解成百位数p3,十位数p2,个位数p1,
- 这样我们的筛选条件就可以写出来:n == p3 * p3 * p3 + p2 * p2 * p2 + p1 * p1 * p1。
- 如何拆分一个三位数n呢?
- 首先求n的个位数:n % 10 然后要将三位数变成两位数:n = n / 10; 对于新的两位数n,又求它的个位数:n % 10
然后要将两位数变成一位数:n = n / 10; - 也就是说我们可以交替使用求余和整除运算将一个三位数拆分,得到它的个位数、十位数和百位数。当然这个分解方法可以推广到任何多位数的拆分。
- 在net.fhl.structure包里创建Example06对象
- 代码如下:
package net.fhl.structure
object Example06 {
def main(args: Array[String]): Unit = {
for (n <- 100 to 999) {
val p1 = n % 10 // 个位数
val p2 = n / 10 % 10 // 十位数
val p3 = n / 100 // 百位数
if (n == p1 * p1 * p1 + p2 * p2 * p2 + p3 * p3 * p3)
println(n.toString + " = " + p3 + "^3 + " + p2 + "^3 + " + p1 + "^3")
}
}
}
- 运行程序,查看结果
五、异常处理
(一)异常处理概述
- Scala中继承了Java的异常机制,提供了程序中产生意外情况时处理的机制,抛出异常的过程和Java中基本一致,通过throw关键字进行:throw
XxxException(),一旦抛出可以当场捕获处理或接着向上抛,捕获异常是通过 try-catch-finally来实现的。
(二)案例演示
- 任务:演示try-catch-finally
- try-catch是有返回值的:如果没有异常就是try语句的返回值,如果有异常就是catch语句的返回值。注意不会是finally的返回值,finally即使有返回值,也会被抛弃,这点和Java是不同的
- 在net.fhl.structure包里创建Example07对象
- 代码如下:
package net.fhl.structure
import java.io.IOException
//演示异常处理
object Example07 {
def main(args: Array[String]): Unit = {
var message = ""
val result = try {
mx()
"恭喜,程序执行正常!"
} catch {
case e: NullPointerException => "空指针异常"
case e: IOException => "呵呵,I/O异常~"
case e: Exception => "管它呢,反正是异常~"
} finally {
message = "程序到此为止!"
"无论是否有异常,都会执行finally里的语句~"
}
println(result)
println(message)
}
def mx(): Unit = {
// throw new RuntimeException("随便抛出一个异常~")
}
}
- 执行程序,查看结果(此时有异常,result取的是catch里的返回值 -
管它呢,反正是异常~,finally语句块执行了的,因此message可以打印出来 - 程序到此为止!)
- 注释掉mx()方法里的语句
- 运行程序,查看结果
六、match结构
(一)语法格式
变量 match {
case 值1 => 表达式1或语句1
case 值2 => 表达式2或语句2
case 值3 => 表达式3或语句3
……
case _ => 表达式n或语句n
}
- Scala中的match类似于其他语言的switch。与Java不同的是,match语句可以应用在任何类型量或表达式上,另外不需要调用break语句,match默认执行完一个case后直接跳出match结构。注意,match是具有返回值的,就是被选到的case的值。
(二)案例演示
- 任务:给城市下评语
- 在net.fhl.structure包里创建Example08对象
package net.fhl.structure
import scala.io.StdIn
//演示match语句
object Example08 {
def main(args: Array[String]): Unit = {
print("输入城市:")
val city = StdIn.readLine();
val comment = city match {
case "北京" => "伟大的首都"
case "上海" => "神奇的魔都"
case "泸州" => "醉人的酒城"
case _ => "一般的城市"
}
print(city + ": " + comment)
}
}
- 运行程序,查看结果
七、变量作用域
(一)Java变量作用域
- Scala中根据不同大括号区分变量作用范围,不允许有叠加,外部看不到内部,内部看不到外部。
1、内部不能访问外部
- 在net.fhl.structure包创建Example09对象
2、外部不能访问内部
- 在net.fhl.structure包创建Example10对象