一、模式匹配
1、采用match关键字声明,每个分支采用case关键字进行声明,当要匹配时会从第一个case分支开始,如果匹配成功,那么执行对应逻辑代码,如果匹配失败,继续执行下一个分支判断,如果所有case都不匹配,那么会执行case_分支。
2、模式守卫,如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。
package chapter01
object PatternMatchCase {
def main(args: Array[String]): Unit = {
val x = 2
val y = x match {
case 1 => "one"
case 2 => "two"
case _ => "other"
}
val a = 25
val b = 90
def matchOp(op: Char): Any = op match {
case '+' => a+b
case '-' => a-b
case _ => "输入非法"
}
println(matchOp('+'))
//模式守卫
def abs(num: Int): Int = {
num match {
case i if i >= 0 => i
case i if i < 0 => -i
}
}
}
}
3、匹配不同类型
package chapter01
object MatchTypes {
def main(args: Array[String]): Unit = {
//1、匹配常量
def describeConst(x: Any): String = x match {
case 1 => "number one"
case "hello" => "hello string"
case true => "true boolean"
case _ => ""
}
//2、匹配类型
def desctibeType(x: Any): String = x match {
case i: Int => "Int" + i
case list: List[String] => "List[String]" + list //List[Int]也会匹配到,存在泛型擦除
case array: Array[int] => "Array[int]" + array.mkString(",") //Array[Int]不会匹配到,不存在泛型擦除
case a => "Something else " + a //获取当前变量,不知道什么类型
}
//3、匹配数组
for (arr <- List(
Array(0),
Array(1, 0),
Array(0, 1, 0),
Array("hello", 2, 3)
)) {
val result = arr match {
case Array(0) => "0"
case Array(x, y) => "Array: " + x + "," + y
case Array(0, _*) => "以0开头的数组"
case Array(x, 1, y) => "中间为1的数组"
case _ => "something else"
}
}
//4、匹配列表-方式一
for (list <- List(
List(0),
List(1, 0),
List(0, 1, 0),
List("hello", 2, 3)
)) {
val result = list match {
case List(0) => "0"
case List(x, y) => "List: " + x + "," + y
case List(0, _*) => "以0开头的列表"
case List(x, 1, y) => "中间为1的列表"
case _ => "something else"
}
}
//4、匹配列表-方式二
val list1 = List(1, 2, 3, 4, 5)
list1 match {
case first :: second :: rest => println(s"first: $first, second: #second: $second, rese: $rest")
case _ => println("something else")
}
//for推导式进行模式匹配
val list3: List[(String, Int)] = List(("a", 12), ("b", 3), ("c", 7))
for (elem <- list3) {
println(elem._1 + " " + elem._2)
}
for ((word, count) <- list3) {
println(word + " " + count)
}
for (("a", count) <- list3) {
println("a" + " " + count)
}
//匹配类的对象实例
val student = new Student("alice", 12)
val result = student match {
case Student("alice", 12) => "Alice 12"
case _ => "Else"
}
}
}
class Student(val name: String, val age: Int)
object Student {
//实现装箱拆箱方法
def apply(name: String, age: Int): Student = new Student(name, age)
//必须实现一个unapply方法,用来对对象属性进行拆解
def unapply(arg: Student): Option[(String, Int)] = {
if (arg == null){
None
}else{
Some((arg.name, arg.age))
}
}
}
//定义样例类,直接匹配,不需要实现装拆箱
case class Student11(name: String, age: Int)
二、偏函数
偏函数也是函数的一种,通过偏函数可以方便的对输入参数做更精确的检查,例如该偏函数的输入类型为List[Int],而我们需要的是第一个元素是0的集合,这就是通过模式匹配实现的。
package chapter01
object PartitialFunctionTest {
def main(args: Array[String]): Unit = {
val list:List[(String, Int)] = List(("a", 12), ("b", 13))
//1、map转换将value*2
val newList = list.map(tuple => (tuple._1, tuple._2 * 2))
//2、用模式匹配对元组元素赋值
val newList2 = list.map(
tuple => {
tuple match {
case (word, count) => (word, count * 2)
}
}
)
//3、省略lambda表达式的写法,即偏函数
val newList3 = list.map {
case (word, count) => (word, count * 2)
}
//偏函数的应用-求绝对值
//针对数据分为不同情形:正负零
val positiveAbs:PartialFunction[Int, Int] = {
case x if x > 0 => x
}
val negativeAbs:PartialFunction[Int, Int] = {
case x if x < 0 => -x
}
val zeroAbs:PartialFunction[Int, Int] = {
case 0 => 0
}
//组合起来
def abs(x: Int): Int = positiveAbs.orElse(negativeAbs).orElse(zeroAbs)(x)
}
}
三、异常处理
package chapter01
object ExceptionTest {
def main(args: Array[String]): Unit = {
try{
val n = 10 /0
}catch{
case e:ArithmeticException =>{
println("发生算数异常")
}
case e: Exception => {
println("发生一般异常")
}
}finally {
println("处理结束")
}
}
}
四、隐式转换
当编译器第一次编译失败的时候,会在当前环境中查找能让代码编译通过的方法,用于将类型进行转换,实现二次编译。隐式转换可以在不需要改任何代码的情况下,扩展某个类的功能。
package chapter01
object ImplicitTest {
def main(args: Array[String]): Unit = {
//隐式函数
implicit def convert(num: Int): MyRIchInt = new MyRIchInt(num)
println(12.myMax(15))
//隐式类
// implicit class MyRIchInt(val self: Int){
// def myMax(n: Int): Int = if(n < self) self else n
// def myMin(n: Int): Int = if (n < self) n else self
// }
//隐式参数,同一作用域范围内同一类型只能有一个隐式值
implicit val str:String = "alice"
implicit val age:Int = 19
def sayHello(implicit name: String): Unit = {
println("hello:" + name)
}
def sayHi(name: String = "alice"): Unit = {
println("hi:" + name)
}
// sayHello()
sayHello
def hiAge(): Unit = {
println("hi, " + implicitly[Int])
}
hiAge()
}
}
class MyRIchInt(val self: Int){
def myMax(n: Int): Int = if(n < self) self else n
def myMin(n: Int): Int = if (n < self) n else self
}
五、泛型
package chapter01
class GenericsTest {
def main(args: Array[String]): Unit = {
//协变和逆变
val child: Parent = new Child
val childList: MyCollection[Parent] = new MyCollection[Parent]
val childList1: MyCollection[Parent] = new MyCollection[Child]
val childList2: MyCollection1[SubChild] = new MyCollection1[Child]
//泛型的上下限
def test[A <: Child](a: A): Unit = {
println(a.getClass.getName)
}
// test[Parent](new Child)//报错,上限为Child
test[Child](new SubChild)
}
}
class Parent {}
class Child extends Parent{}
class SubChild extends Child{}
class MyCollection[+E]{}
class MyCollection1[-E]{}