01.条件表达式
a.if表达式
val result = if (x > 0) "positive" else "negative"
if是表达式,有返回值
可以赋值给变量
类型是两个分支的公共父类型
b.if-else if-else
val grade = if (score >= 90) "A"
else if (score >= 80) "B"
else if (score >= 70) "C"
else "D"
多分支条件
返回匹配分支的值
c.三元运算符
Scala没有三元运算符
使用if-else表达式代替
更清晰易读
02.循环结构
a.while循环
while (condition) {
// 循环体
}
条件为真时执行
可能一次都不执行
b.do-while循环
do {
// 循环体
} while (condition)
至少执行一次
后判断条件
c.for循环
for (i <- 1 to 10) { println(i) }
遍历范围
1 to 10:包含10
1 until 10:不包含10
d.for推导式
for (i <- 1 to 10 if i % 2 == 0) yield i * 2
带条件的循环
yield生成新集合
函数式风格
03.模式匹配
a.match表达式
x match {
case 1 => "one"
case 2 => "two"
case _ => "other"
}
类似switch但更强大
是表达式,有返回值
_是通配符
b.类型匹配
x match {
case s: String => s.length
case i: Int => i * 2
case _ => 0
}
匹配类型
自动类型转换
c.守卫条件
x match {
case n if n > 0 => "positive"
case n if n < 0 => "negative"
case _ => "zero"
}
添加额外条件
if守卫
d.样例类匹配
person match {
case Person(name, age) if age >= 18 => s"$name is adult"
case Person(name, _) => s"$name is minor"
}
解构样例类
提取字段值
04.异常处理
a.try-catch
try {
// 可能抛异常的代码
} catch {
case e: IOException => println("IO error")
case e: Exception => println("Error")
}
捕获异常
模式匹配语法
b.try-catch-finally
try {
// 代码
} catch {
case e: Exception => // 处理
} finally {
// 清理资源
}
finally总是执行
用于资源清理
c.抛出异常
throw new IllegalArgumentException("Invalid")
使用throw关键字
异常是表达式,类型是Nothing
05.循环控制
a.break和continue
Scala没有break和continue
使用其他方式实现
函数式风格避免使用
b.替代方案
使用return提前返回
使用布尔标志控制
使用takeWhile等高阶函数
使用scala.util.control.Breaks
2.5 函数定义
01.基本函数定义
a.完整形式
def add(x: Int, y: Int): Int = {
x + y
}
def关键字
参数类型必须声明
返回类型可以推断
b.简化形式
def add(x: Int, y: Int) = x + y
单行表达式
省略花括号
省略return
c.无参函数
def hello() = "Hello"
def hello = "Hello" // 无括号
调用时可以省略括号
副作用操作建议加括号
02.参数特性
a.默认参数
def greet(name: String = "World") = s"Hello, $name"
提供默认值
调用时可以省略
greet()或greet("Alice")
b.命名参数
def divide(dividend: Int, divisor: Int) = dividend / divisor
divide(divisor = 2, dividend = 10)
指定参数名
改变参数顺序
c.可变参数
def sum(nums: Int*) = nums.sum
*表示可变参数
接收任意数量参数
sum(1, 2, 3, 4)
d.传名参数
def byName(x: => Int) = { x; x }
=>表示传名参数
每次使用时求值
用于惰性求值
03.返回值
a.显式返回
def max(x: Int, y: Int): Int = {
if (x > y) return x
y
}
使用return关键字
提前返回
不推荐使用
b.隐式返回
def max(x: Int, y: Int) = if (x > y) x else y
最后一个表达式的值
函数式风格
推荐使用
c.Unit返回
def printSum(x: Int, y: Int): Unit = {
println(x + y)
}
无返回值
副作用操作
返回()
04.函数类型
a.函数类型声明
val add: (Int, Int) => Int = (x, y) => x + y
(参数类型) => 返回类型
函数作为值
b.高阶函数
def operate(x: Int, y: Int, f: (Int, Int) => Int) = f(x, y)
函数作为参数
operate(3, 4, (a, b) => a + b)
c.函数作为返回值
def multiplier(factor: Int): Int => Int = {
(x: Int) => x * factor
}
返回函数
闭包
05.递归函数
a.普通递归
def factorial(n: Int): Int = {
if (n <= 1) 1
else n * factorial(n - 1)
}
必须显式声明返回类型
可能栈溢出
b.尾递归
@tailrec
def factorial(n: Int, acc: Int = 1): Int = {
if (n <= 1) acc
else factorial(n - 1, n * acc)
}
尾递归优化
不会栈溢出
使用@tailrec注解检查
2.6 方法与函数
01.方法定义
a.类方法
class Calculator {
def add(x: Int, y: Int) = x + y
}
定义在类中
使用def关键字
可以访问类成员
b.对象方法
object Math {
def square(x: Int) = x * x
}
定义在单例对象中
类似静态方法
全局访问
02.方法与函数区别
a.定义方式
方法:def定义,属于类或对象
函数:val定义,是对象
方法可以转换为函数
b.参数列表
方法:可以有多个参数列表
函数:只能有一个参数列表
def m(x: Int)(y: Int) = x + y
c.类型参数
方法:可以有类型参数
函数:不能有类型参数
def identity[T](x: T) = x
d.默认参数
方法:支持默认参数
函数:不直接支持
需要通过方法转换
03.方法转函数
a.eta展开
def add(x: Int, y: Int) = x + y
val f = add _
使用下划线转换
方法变为函数对象
b.自动转换
List(1, 2, 3).map(add)
编译器自动转换
高阶函数参数位置
04.柯里化方法
a.多参数列表
def add(x: Int)(y: Int) = x + y
多个参数列表
部分应用
add(1)(2)
b.部分应用
val addOne = add(1) _
固定部分参数
返回新函数
addOne(2) // 结果3
c.应用场景
类型推断
隐式参数
DSL设计
2.7 代码块与作用域
01.代码块
a.块表达式
val result = {
val x = 10
val y = 20
x + y
}
花括号包围
最后一个表达式是返回值
可以包含多个语句
b.块作用域
代码块内定义的变量
只在块内可见
块外不可访问
避免命名冲突
c.嵌套块
{
val x = 10
{
val y = 20
x + y // 可以访问外层x
}
}
内层可以访问外层
外层不能访问内层
02.作用域规则
a.词法作用域
变量在定义位置可见
内层可以访问外层
遵循最近定义原则
b.变量遮蔽
val x = 10
{
val x = 20 // 遮蔽外层x
println(x) // 输出20
}
内层变量遮蔽外层
外层变量仍然存在
c.对象作用域
类成员在整个类中可见
private限制访问范围
protected子类可见
03.导入作用域
a.包导入
import scala.collection.mutable.ArrayBuffer
导入特定类
在当前作用域可用
b.通配符导入
import scala.collection.mutable._
导入包中所有类
使用下划线
c.选择性导入
import scala.collection.mutable.{ArrayBuffer, HashMap}
导入多个类
花括号包围
d.重命名导入
import scala.collection.mutable.{HashMap => MutableHashMap}
导入时重命名
避免命名冲突
e.隐藏导入
import scala.collection.mutable.{HashMap => _, _}
隐藏特定类
导入其他所有类
04.作用域最佳实践
a.最小作用域原则
变量定义在最小需要的作用域
减少变量生命周期
提高代码可读性
b.避免变量遮蔽
使用不同的变量名
减少混淆
提高代码清晰度
c.合理使用导入
只导入需要的类
避免通配符导入
使用包对象组织导入
3 面向对象
3.1 类与对象
01.类定义
a.基本类
class Person {
var name: String = ""
var age: Int = 0
}
使用class关键字
定义字段和方法
默认public访问
b.主构造器
class Person(val name: String, var age: Int)
参数列表即主构造器
val生成只读字段
var生成可读写字段
c.辅助构造器
class Person(val name: String) {
var age: Int = 0
def this(name: String, age: Int) = {
this(name)
this.age = age
}
}
使用this关键字
必须调用主构造器或其他辅助构造器
可以有多个辅助构造器
02.对象创建
a.使用new
val p = new Person("Alice", 25)
new关键字创建实例
调用构造器
b.工厂方法
object Person {
def apply(name: String, age: Int) = new Person(name, age)
}
val p = Person("Alice", 25)
省略new关键字
使用伴生对象的apply方法
c.匿名类
val p = new Person("Alice", 25) {
override def toString = s"Person($name, $age)"
}
创建时重写方法
一次性使用
03.字段和方法
a.字段定义
class Person {
val name: String = "Unknown" // 不可变
var age: Int = 0 // 可变
private var id: Int = 0 // 私有
}
val:只读字段
var:可读写字段
可以指定访问修饰符
b.方法定义
class Person(val name: String) {
def greet() = s"Hello, I'm $name"
def greet(other: String) = s"Hello $other, I'm $name"
}
使用def关键字
支持方法重载
可以访问字段
c.getter和setter
class Person {
private var _age: Int = 0
def age = _age
def age_=(value: Int): Unit = {
if (value >= 0) _age = value
}
}
自定义访问器
age_=是setter方法
可以添加验证逻辑
3.2 构造器
01.主构造器
a.参数定义
class Person(val name: String, var age: Int)
紧跟类名的参数列表
val/var生成字段
不加修饰符则为私有参数
b.构造器代码
class Person(val name: String) {
println(s"Creating person: $name")
val timestamp = System.currentTimeMillis()
}
类体中的语句
对象创建时执行
初始化字段
c.私有构造器
class Person private(val name: String)
private修饰主构造器
外部不能直接创建对象
通过伴生对象创建
02.辅助构造器
a.定义方式
class Person(val name: String) {
var age: Int = 0
def this(name: String, age: Int) = {
this(name)
this.age = age
}
}
使用this作为方法名
必须首先调用主构造器或其他辅助构造器
b.多个辅助构造器
class Person(val name: String) {
var age: Int = 0
var email: String = ""
def this(name: String, age: Int) = {
this(name)
this.age = age
}
def this(name: String, age: Int, email: String) = {
this(name, age)
this.email = email
}
}
构造器链
灵活的对象创建方式
03.构造器参数
a.val参数
class Person(val name: String)
生成私有字段
生成公共getter
不可变
b.var参数
class Person(var age: Int)
生成私有字段
生成公共getter和setter
可变
c.普通参数
class Person(name: String)
不生成字段
只在构造器中可用
用于初始化逻辑
d.默认参数
class Person(val name: String = "Unknown", var age: Int = 0)
提供默认值
创建对象时可以省略
new Person()或new Person("Alice")
3.3 继承与重写
01.类继承
a.基本继承
class Student extends Person
使用extends关键字
只能继承一个类
继承所有非私有成员
b.调用父类构造器
class Student(name: String, age: Int, val grade: String)
extends Person(name, age)
子类构造器调用父类构造器
传递参数给父类
c.final类
final class Person
不能被继承
防止继承
类似Java的final
02.方法重写
a.重写方法
class Student extends Person {
override def greet() = s"Hi, I'm student $name"
}
使用override关键字
必须显式声明override
编译器检查
b.重写字段
class Student extends Person {
override val name = "Student"
}
val可以重写val或def
var不能重写
c.super调用
class Student extends Person {
override def greet() = super.greet() + " (student)"
}
使用super访问父类
调用父类方法
扩展父类行为
03.抽象成员
a.抽象方法
abstract class Shape {
def area(): Double
}
没有方法体
子类必须实现
不需要override关键字
b.抽象字段
abstract class Shape {
val color: String
}
没有初始值
子类必须提供值
c.实现抽象成员
class Circle(val radius: Double) extends Shape {
override val color = "red"
def area() = Math.PI * radius * radius
}
提供具体实现
抽象方法不需要override
抽象字段需要override或val/var
3.4 特质(Trait)
01.特质定义
a.基本特质
trait Flyable {
def fly(): Unit
}
使用trait关键字
可以有抽象方法
类似接口
b.具体方法
trait Flyable {
def fly(): Unit = println("Flying")
def land(): Unit = println("Landing")
}
可以有具体实现
提供默认行为
c.字段
trait Flyable {
val maxAltitude: Int
var currentAltitude: Int = 0
}
可以有抽象和具体字段
子类必须实现抽象字段
02.特质混入
a.单特质混入
class Bird extends Flyable
使用extends混入第一个特质
实现抽象成员
b.多特质混入
class Bird extends Animal with Flyable with Singable
使用with混入多个特质
实现所有抽象成员
顺序很重要
c.对象混入
val bird = new Bird with Flyable
创建对象时混入特质
动态混入
灵活组合行为
03.特质线性化
a.混入顺序
class Bird extends A with B with C
线性化顺序:Bird -> C -> B -> A
从右到左
super调用遵循线性化顺序
b.方法解析
多个特质有同名方法
调用最右边特质的方法
使用super调用链式调用
c.菱形继承
trait A { def m() }
trait B extends A { override def m() = super.m() }
trait C extends A { override def m() = super.m() }
class D extends B with C
线性化解决冲突
C的方法优先
04.特质应用
a.接口定义
trait Repository {
def save(data: String): Unit
def load(id: Int): String
}
定义契约
多个实现
b.功能混入
trait Logging {
def log(msg: String) = println(s"[LOG] $msg")
}
class Service extends Logging {
def process() = {
log("Processing")
}
}
添加横切功能
代码复用
c.堆叠修改
trait DoubleQueue extends Queue {
abstract override def put(x: Int) = super.put(2 * x)
}
修改父类行为
abstract override
链式调用
3.5 抽象类
01.抽象类定义
a.基本定义
abstract class Shape {
def area(): Double
def perimeter(): Double
}
使用abstract关键字
可以有抽象方法
不能实例化
b.具体成员
abstract class Shape {
val color: String = "black"
def draw() = println(s"Drawing $color shape")
def area(): Double
}
可以有具体方法和字段
混合抽象和具体
c.构造参数
abstract class Shape(val color: String) {
def area(): Double
}
可以有构造参数
子类必须传递参数
02.抽象类vs特质
a.构造参数
抽象类:可以有构造参数
特质:不能有构造参数(Scala 2)
Scala 3特质支持参数
b.多继承
抽象类:只能继承一个
特质:可以混入多个
特质更灵活
c.使用场景
抽象类:需要构造参数,表示is-a关系
特质:定义可混入的行为,表示has-a关系
根据需求选择
03.抽象类型
a.类型成员
abstract class Buffer {
type T
val element: T
}
抽象类型成员
子类指定具体类型
b.类型实现
class IntBuffer extends Buffer {
type T = Int
val element = 42
}
指定具体类型
类型安全
c.类型边界
abstract class Buffer {
type T <: AnyVal
val element: T
}
约束类型范围
类型上界
3.6 样例类(Case Class)
01.样例类定义
a.基本定义
case class Person(name: String, age: Int)
使用case关键字
自动生成很多功能
不可变对象
b.自动生成功能
自动生成apply方法
自动生成unapply方法
自动生成toString,equals,hashCode
自动生成copy方法
参数自动变为val
02.样例类特性
a.创建对象
val p = Person("Alice", 25)
不需要new关键字
使用apply方法
简洁语法
b.模式匹配
person match {
case Person(name, age) => println(s"$name is $age")
}
支持解构
提取字段值
强大的匹配能力
c.copy方法
val p1 = Person("Alice", 25)
val p2 = p1.copy(age = 26)
创建修改后的副本
原对象不变
命名参数指定修改字段
d.相等性
Person("Alice", 25) == Person("Alice", 25) // true
基于值比较
自动实现equals和hashCode
结构相等
03.样例对象
a.定义
case object Singleton
单例样例对象
可以用于模式匹配
枚举值
b.应用场景
表示枚举值
表示特殊状态
模式匹配的常量
04.样例类最佳实践
a.不可变性
使用val而非var
保持不可变
线程安全
b.模式匹配
充分利用解构
简化代码
提高可读性
c.数据传输
DTO对象
消息对象
配置对象
3.7 伴生对象
01.伴生对象概念
a.定义
class Person(val name: String)
object Person {
def apply(name: String) = new Person(name)
}
与类同名的object
在同一个文件中
可以互相访问私有成员
b.作用
工厂方法
静态方法
常量定义
隐式转换
02.工厂方法
a.apply方法
object Person {
def apply(name: String, age: Int) = new Person(name, age)
}
val p = Person("Alice", 25)
省略new关键字
灵活的对象创建
b.多个工厂方法
object Person {
def apply(name: String) = new Person(name, 0)
def apply(name: String, age: Int) = new Person(name, age)
def fromString(s: String) = {
val parts = s.split(",")
new Person(parts(0), parts(1).toInt)
}
}
重载apply方法
提供不同创建方式
命名工厂方法
03.访问私有成员
a.类访问对象私有成员
class Person(val name: String) {
private val id = Person.nextId()
}
object Person {
private var currentId = 0
private def nextId() = {
currentId += 1
currentId
}
}
类可以访问伴生对象私有成员
共享状态
b.对象访问类私有成员
class Person(private val ssn: String)
object Person {
def validate(p: Person) = p.ssn.length == 9
}
对象可以访问类私有成员
封装验证逻辑
04.伴生对象应用
a.常量定义
object MathConstants {
val PI = 3.14159
val E = 2.71828
}
全局常量
类似静态常量
b.隐式转换
object Conversions {
implicit def intToString(x: Int): String = x.toString
}
定义隐式转换
放在伴生对象中
自动导入
c.枚举
object Color {
val Red = 0
val Green = 1
val Blue = 2
}
模拟枚举
使用sealed trait更好
01.匿名函数语法
a.完整形式
(x: Int, y: Int) => x + y
参数列表
=>符号
函数体
b.类型推断
List(1, 2, 3).map((x: Int) => x * 2)
List(1, 2, 3).map(x => x * 2)
编译器推断参数类型
简化语法
c.下划线简写
List(1, 2, 3).map(_ * 2)
_代表参数
每个_代表不同参数
最简洁形式
02.多参数匿名函数
a.两个参数
(x: Int, y: Int) => x + y
List(1, 2, 3).reduce((a, b) => a + b)
List(1, 2, 3).reduce(_ + _)
下划线按顺序对应参数
b.多个下划线
val f = (_: Int) + (_: Int)
f(3, 4) // 7
需要指定类型
每个_是独立参数
03.匿名函数应用
a.集合操作
List(1, 2, 3).map(_ * 2).filter(_ > 3)
链式调用
简洁表达
b.回调函数
button.onClick(() => println("Clicked"))
事件处理
异步操作
c.临时逻辑
val sorted = list.sortWith((a, b) => a.length < b.length)
自定义排序
一次性逻辑
4.3 闭包
01.闭包概念
a.定义
def makeAdder(x: Int) = (y: Int) => x + y
val add5 = makeAdder(5)
函数引用外部变量
捕获变量值
形成闭包
b.自由变量
外部作用域的变量
被内部函数引用
闭包捕获这些变量
c.闭包特性
函数+环境
变量生命周期延长
每个闭包独立
02.闭包示例
a.计数器
def makeCounter() = {
var count = 0
() => {
count += 1
count
}
}
val counter = makeCounter()
counter() // 1
counter() // 2
封装状态
私有变量
b.累加器
def makeAccumulator(init: Int) = {
var sum = init
(x: Int) => {
sum += x
sum
}
}
val acc = makeAccumulator(0)
acc(5) // 5
acc(3) // 8
维护状态
03.闭包注意事项
a.变量捕获
闭包捕获变量引用
不是变量值
变量改变影响闭包
b.内存管理
闭包持有变量引用
可能导致内存泄漏
注意生命周期
c.线程安全
共享可变状态
需要同步
优先使用不可变
4.4 柯里化
01.柯里化概念
a.定义
def add(x: Int)(y: Int) = x + y
多个参数列表
逐个应用参数
返回函数
b.部分应用
val add5 = add(5) _
add5(3) // 8
固定部分参数
生成新函数
c.自动柯里化
def add(x: Int, y: Int) = x + y
val curriedAdd = (add _).curried
curriedAdd(5)(3) // 8
转换为柯里化形式
02.柯里化优势
a.参数复用
def log(level: String)(message: String) =
println(s"[$level] $message")
val info = log("INFO") _
val error = log("ERROR") _
info("App started")
error("Error occurred")
创建特定配置的函数
b.类型推断
def foldLeft[A, B](list: List[A])(z: B)(f: (B, A) => B): B
第一个参数列表确定类型A
后续参数列表可以推断类型
改善类型推断
c.DSL设计
def select(columns: String*)(from: String)(where: String) =
s"SELECT ${columns.mkString(",")} FROM $from WHERE $where"
select("name", "age")("users")("age > 18")
构建领域特定语言
提高可读性
03.柯里化实践
a.隐式参数
def greet(name: String)(implicit greeting: String) =
s"$greeting, $name"
implicit val defaultGreeting = "Hello"
greet("Alice") // "Hello, Alice"
最后一个参数列表可以是隐式的
自动传递上下文
b.控制结构
def withResource[A, B](resource: A)(f: A => B): B = {
try { f(resource) }
finally { /* cleanup */ }
}
withResource(openFile("data.txt")) { file =>
file.readLines()
}
自定义控制结构
资源管理
c.函数组合
val f = (x: Int) => x + 1
val g = (x: Int) => x * 2
val h = f.andThen(g)
h(3) // 8
组合多个函数
4.5 偏函数
01.偏函数定义
a.PartialFunction
val divide: PartialFunction[Int, Int] = {
case d if d != 0 => 42 / d
}
只处理部分输入
使用case语句
未定义输入抛异常
b.isDefinedAt方法
divide.isDefinedAt(2) // true
divide.isDefinedAt(0) // false
检查是否定义
避免异常
c.应用
divide(2) // 21
divide(0) // MatchError
只能用于定义的输入
02.偏函数组合
a.orElse组合
val handle1: PartialFunction[Int, String] = {
case 1 => "one"
}
val handle2: PartialFunction[Int, String] = {
case 2 => "two"
}
val handle = handle1 orElse handle2
handle(1) // "one"
handle(2) // "two"
链接多个偏函数
依次尝试
b.andThen组合
val f: PartialFunction[Int, Int] = { case x => x * 2 }
val g: PartialFunction[Int, String] = { case x => x.toString }
val h = f andThen g
h(5) // "10"
串联偏函数
输出作为输入
03.偏函数应用
a.集合操作
List(1, 2, 3, 4).collect {
case x if x % 2 == 0 => x * 2
} // List(4, 8)
collect方法使用偏函数
过滤并转换
b.模式匹配
val result = value match {
case x if x > 0 => "positive"
case x if x < 0 => "negative"
}
match表达式是偏函数
处理特定模式
c.Actor消息处理
def receive: PartialFunction[Any, Unit] = {
case Start => println("Starting")
case Stop => println("Stopping")
}
Actor的receive方法
处理特定消息类型
4.6 模式匹配
01.基本模式匹配
a.常量模式
x match {
case 0 => "zero"
case 1 => "one"
case _ => "other"
}
匹配常量值
_是通配符
b.变量模式
x match {
case n => s"The value is $n"
}
绑定到变量
总是匹配
c.类型模式
x match {
case s: String => s.length
case i: Int => i * 2
case _ => 0
}
匹配类型
自动类型转换
02.构造器模式
a.样例类匹配
person match {
case Person(name, age) => s"$name is $age"
}
解构样例类
提取字段值
b.嵌套匹配
person match {
case Person(name, Address(city, _)) => s"$name lives in $city"
}
匹配嵌套结构
深度解构
c.序列模式
list match {
case List(1, 2, 3) => "exact match"
case List(1, _*) => "starts with 1"
case head :: tail => s"head: $head"
case Nil => "empty"
}
匹配列表
_*匹配任意元素
::匹配头尾
03.守卫条件
a.if守卫
x match {
case n if n > 0 => "positive"
case n if n < 0 => "negative"
case _ => "zero"
}
添加额外条件
更精确匹配
b.复杂条件
person match {
case Person(name, age) if age >= 18 && name.startsWith("A") =>
"Adult with name starting with A"
}
组合多个条件
灵活匹配
04.模式匹配应用
a.Option处理
option match {
case Some(value) => println(value)
case None => println("No value")
}
处理可选值
避免null
b.Either处理
result match {
case Right(value) => println(s"Success: $value")
case Left(error) => println(s"Error: $error")
}
处理成功或失败
错误处理
c.Try处理
Try(riskyOperation()) match {
case Success(result) => println(result)
case Failure(exception) => println(exception.getMessage)
}
异常处理
函数式风格
4.7 Option类型
01.Option概念
a.定义
sealed abstract class Option[+A]
case class Some[+A](value: A) extends Option[A]
case object None extends Option[Nothing]
表示可选值
避免null
类型安全
b.创建Option
val some: Option[Int] = Some(42)
val none: Option[Int] = None
Option(null) // None
Option(42) // Some(42)
安全创建
02.Option操作
a.获取值
option.get // 不安全,可能抛异常
option.getOrElse(0) // 提供默认值
option.orElse(Some(0)) // 提供备选Option
安全获取值
b.判断存在
option.isDefined // 是否有值
option.isEmpty // 是否为空
option.nonEmpty // 是否非空
检查状态
c.转换操作
option.map(_ * 2) // 转换值
option.flatMap(x => Some(x * 2)) // 扁平化映射
option.filter(_ > 0) // 过滤
链式操作
03.Option模式匹配
a.基本匹配
option match {
case Some(value) => println(value)
case None => println("No value")
}
模式匹配处理
清晰表达
b.for推导式
for {
x <- option1
y <- option2
} yield x + y
组合多个Option
自动处理None
04.Option最佳实践
a.避免get
不要使用option.get
使用getOrElse或模式匹配
避免异常
b.链式操作
option.map(_ * 2).filter(_ > 10).getOrElse(0)
函数式风格
简洁表达
c.与Java互操作
import scala.jdk.OptionConverters._
javaOptional.toScala
scalaOption.toJava
转换Java Optional
4.8 异常处理
01.Try类型
a.定义
sealed abstract class Try[+T]
case class Success[+T](value: T) extends Try[T]
case class Failure[+T](exception: Throwable) extends Try[T]
表示可能失败的计算
函数式异常处理
b.创建Try
Try(riskyOperation())
Success(42)
Failure(new Exception("Error"))
捕获异常
02.Try操作
a.转换操作
Try(10 / 2).map(_ * 2) // Success(10)
Try(10 / 0).map(_ * 2) // Failure
map转换成功值
失败传播
b.恢复操作
Try(10 / 0).recover {
case _: ArithmeticException => 0
}
recover处理特定异常
返回默认值
c.组合操作
for {
x <- Try(10 / 2)
y <- Try(20 / 4)
} yield x + y
组合多个Try
任一失败则失败
03.Either类型
a.定义
sealed abstract class Either[+A, +B]
case class Left[+A](value: A) extends Either[A, Nothing]
case class Right[+B](value: B) extends Either[Nothing, B]
表示两种可能的值
Left通常表示错误
Right表示成功
b.使用Either
def divide(a: Int, b: Int): Either[String, Int] = {
if (b == 0) Left("Division by zero")
else Right(a / b)
}
返回错误信息或结果
类型安全
c.Either操作
either.map(_ * 2) // 操作Right值
either.left.map(_.toUpperCase) // 操作Left值
either.getOrElse(0) // 获取Right值或默认值
灵活处理
04.异常处理最佳实践
a.使用Try
优先使用Try而非try-catch
函数式风格
易于组合
b.使用Either
需要详细错误信息时使用Either
Left存储错误详情
Right存储成功结果
c.避免异常
使用Option表示可选值
使用Try表示可能失败
使用Either表示错误详情
减少异常使用