Higher-Order Functions
def 定义的是方法,而不是函数
- 函数可作为变量存在,可直接调用,也可作为值传递给其他函数
_ 后缀将普通方法变为函数: ceil _
- 根据上下文编译器可以自动将方法转换为函数,也可省略
_ 后缀
- 高阶函数,接收函数的函数
- 参数类型推导
- 匿名函数传递给其他函数或方法时,如果一直到参数类型,则可省略匿名函数的参数类型,可自动推导类型
- 参数只有一个时可省略括号
- 闭包 Closures,特定作用域
- SAM, single abstract method interface
- 对应 Java 中的函数式接口 (1.8)
- 可将 Scala 函数传递给 Java,只在函数字面量中起作用
- 柯里化 Currying
- 将接收两个参数的函数变为接收第一个参数的函数,该函数返回一个消费第二个参数的函数
- 控制抽象 Control Abstractions
- Scala 只包含少量的流程控制语句,用户可自定义控制语句
Pattern Matching and Case Classes
- 可对任何类型进行模式匹配,匹配顺序从上至下
- 模式匹配代替
switch,默认分支为 case _;可避免 switch 语句中因缺少 break 带来的 fall-through 问题
- 模式匹配也是表达式,可将其返回值直接赋值给变量
- 模式守卫 / guards,为匹配设置条件,任何
Boolean 条件都可作为模式守卫;case ... if ... => ...
case 关键字后接变量名或对应数据结构中使用变量名,那么匹配项就赋值给该变量,变量名必须以小写字母开头
- 使用
| 分隔同一匹配的多个可选项,此时不可使用变量绑定元素
- 类型匹配,代替
isInstanceOf 和 asInstanceOf,直接进行类型转换
- 必须为类型指定变量名,否则匹配的是实际的类型对象
- 匹配在运行时发生,而 JVM 泛型会被擦除
- 不可以匹配具体的
Map 类型(可使用 case Map[_, _],不可使用 case Map[Int, Int])
Array 的类型不会被擦除
- 解构 destructuring
case Array(x, y) => s"$x $y" // 匹配长度为2的数组,并将分别绑定到 x, y
case Array(0, rest @ _*) => rest.min // 可变参数
case x :: y :: Nil => ... // 绑定参数
case head :: tail => ... // 解构 head , tail
case (0, _) => ... // 匹配第一个元素为0
case (x, y) => ... // 绑定参数
- 定义变量,注意一定要小写开头;其实等价于
match 模式匹配加上赋值操作
val (x, y) = (1, 2)
val Array(f, s, rest @ _*) = arr
- 用于
for 循环遍历集合,匹配符合条件的元素
for ((k, v) <- System.getProperties()) println(s"$k $v")
// 匹配 value 为 "" 的项,其他的则被忽略
for ((k, "") <- System.getProperties()) println(k)
// if guard 过滤
for ((k, v) <- System.getProperties() if v == "") println(k)
- Case Class
- 用于模式匹配的特殊类
- 构造参数默认为
val,默认提供 apply、unapply、toString、equals、hashCode、copy
copy 用于复制对象时,可使用命名参数来修改属性
case class X 使用时 case X() => ...,需要括号
case object S 单例,使用时 case S => ..., 不要括号
:: 也是 case class,配合中缀表达式,就是常见的匹配方式,case head :: tail,实际调用 ::(head, tail)
- 可用于嵌套的结构;绑定变量、可变参数匹配类似
- 适用于固定结构的类,如
List 等
sealed 密封的
- 被修饰的类,则其子类必须和该类在同一个文件中定义
- 在编译时即确定了所有匹配项的可能性
Option 也是使用 case class 来表示是否有值存在的
- 子类
Some 封装值,子类 None 表示无值
- 相比使用
"" 或 null 更加安全
Map 进行 get 操作返回的也是 Option,也可使用模式匹配来处理
getOrElse 尝试获取值,未获取到则使用给定的值
- Partial Function 偏函数
- 没有对所有输入进行定义的函数
apply 从模式匹配中计算函数值,isDefinedAt 判断输入是否匹配定义的模式
case 语句块是偏函数
PartialFunction[A, B] 的实例, A 为输入类型,B 为输出类型
- 可使用偏函数的
lift 方法,将偏函数变为常规函数,返回值为 Option[B]
- 也可以通过
Function.unlift 将返回 Option[B] 的函数变为偏函数
Seq[A] 也是偏函数 PartialFunction[Int, A]
Map[K, V] 也是偏函数 PartialFunction[K, V]
catch 语句也是偏函数,可在 catch 块中使用模式匹配处理异常
注解
- Scala 中注解可影响代码编译,如
@BeanProperty 会自动生成 getter/setter
- 可用于 类、方法、字段、变量、参数等
- 多个注解无顺序
- 主构造器的注解,需要加括号
class Credential @Inject() (var username: String, var password: String)
- 表达式的注解,使用分号加注解的方式
(map.get(key): @unchecked) ...
- 类型参数的注解,
class Test[@specialized T]
- 实际类型的注解,放在类型之后,
def name: String @Localized
- 注解实现
- 注解必须继承
Annotation
- 类型注解必须继承
TypeAnnotation
- 元注解
@param, @field, @getter, @setter, @beanGetter, @beanSetter
- 对应 Java 修饰符、标记接口
@volatile 对应 volatile 关键字
@transient 对应 transient 关键字
@strictfp 对应 strictfp 关键字
@native 对应 native 关键字
@cloneable 对应 Cloneable
@remote 对应 java.rmi.Remote
@SerialVersionUID 代替序列化字段
- 使用
@throws(classOf[Exception]) 来处理 Java 中的受检异常
@varargs 处理可变参数
@varargs def name(args: String*) 生成 void name(String... args)
- 没有
@varargs 则可变参数会被转换成 Seq[T]
- 优化
@tailrec 会尝试优化尾递归调用,将其变为循环
@switch 编译器会检查 match 表达式是否编译为 ableswitch` 或 `lookupswitch,如果被编译成一系列条件表达式,则会抛出异常
@inline, @noinline 建议编译器是否将方法替换为行内调用
@elidable, 用于标注在生产代码中可移除的方法
elidable 对象定义了很多级别常量可直接使用,未指定参数时默认是 SERVERE 即 1000(包含1000)
@specialized 处理基础类型,自动生成基础类型对应包装类的方法