一、option类型
定义:通过该类型可以有效的避免空指针异常
1 def func(a: Double, b: Double): Option[Double] = { 2 if (b != 0) { 3 //没错的情况下 返回值用Some函数包起来 4 Some(a / b) 5 } else { 6 //无值 返回None 7 None 8 } 9 } 10 11 def main(args: Array[String]): Unit = { 12 var a = func(2.0, 2.0) 13 println(a) 14 //查看返回值的方法 15 println(a.getOrElse(0.0)) 16 //Some(1.0) 17 //1.0 18 19 }
二、偏函数
格式:val 函数名:PartialFunction[参数类型,返回值类型]={
case 1 => "..."
case 2 => "..."
case _ => "其他"
}
1 val cmm: PartialFunction[Int, String] = { 2 case 1 => "1" 3 case 2 => "2" 4 case _ => "其他" 5 } 6 println(cmm(1)) 7 println(cmm(2)) 8 println(cmm(3)) 9 //1 10 //2 11 //其他
1 //把偏函数作为其他方法的参数传入,类比函数化编程 2 var li = 1.to(10).toList 3 //需求:将列表的每一个元素转换成属于他的范围 4 var m = li.map { 5 case m if m >= 1 && m <= 3 => "[1-3]" 6 case m if m >= 4 && m <= 7 => "[4-7]" 7 case m if m > 7 => "[7-*]" 8 } 9 println(m) 10 //List([1-3], [1-3], [1-3], [4-7], [4-7], [4-7], [4-7], [7-*], [7-*], [7-*])
三、正则表达式
格式:var 变量名:Regex =""" 规则""".r
1 //正则表达式 2 var r: Regex = 3 """.+@.+..+""".r 4 var x = "1234@qq.com" 5 //该方法返回一个迭代器 6 var res = r.findAllMatchIn(x) 7 print(res.next()) 8 //1234@qq.com
四、异常处理
格式:try{代码}
catch{
//异常处理
case ex:Exception【错误类型】 => "返回值"
...
}
finally{最后都会执行的代码}
1 try { 2 2 / 0 3 } 4 catch { 5 case ex: ArithmeticException => println("除数不可以是0") 6 } 7 finally { 8 println("无论如何最后我都会执行的") 9 } 10 //除数不可以是0 11 //无论如何最后我都会执行的
主动抛出异常:throw new Exception("这是我自己主动抛出的异常")
五、提取器
定义:把对象相关属性,通过${} 提取,样例类实现了提取器,而普通的类没有提取器之说
本质:就是把一个对象的属性 获取出来 通过元祖的形式返回
1 case class Person(var name: String) 2 3 4 def main(args: Array[String]): Unit = { 5 var a: Any = Person("cmx") 6 a match { 7 case Person(name) => println(s"${name}") 8 } 9 //结果 10 //cmx 11 }
自定义提取器:提取器只能定义在伴生对象中,且于apply方法成对出现
注意:提取器的 返回值是多个的话用元组括起来,只有一个的话直接返回即可
1 class Person(var name: String) 2 3 4 object Person { 5 //快速创建对象的方法 6 def apply(name: String) = { 7 new Person(name) 8 } 9 10 //提取器 :参数类型:与类保持一致,返回值使用Option,避免空指针 11 def unapply(arg: Person): Option[String] = { 12 if (arg != null) { 13 Some(arg.name) 14 } else { 15 None 16 } 17 } 18 } 19 20 class User(var id: Int, var name: String) 21 22 object User { 23 def apply(id: Int, name: String) = new User(id, name) 24 25 //完整写法 26 //def unapply(arg: User): Option[(Int, String)] 27 //简写 利用类型推导 28 def unapply(arg: User) = { 29 var res = (arg.id, arg.name) 30 Some(res) 31 } 32 } 33 34 def main(args: Array[String]): Unit = { 35 //定义时使用Any 防止模式匹配时不知是那个类型 36 var a: Any = Person("cmx") 37 var b: Any = User(1, "cmx01") 38 39 a match { 40 case Person(name) => println(s"${name}") 41 case User(id, name) => println(s"${id}${name}") 42 } 43 //cmx 44 b match { 45 case Person(name) => println(s"${name}") 46 case User(id, name) => println(s"${id}${name}") 47 } 48 //1cmx01 49 50 }
六、泛型 Array[Int] --> 具体类型
1.泛型类:可以根据需要,随意改变属性的类型
1 class Cmx[T](var name: T) { 2 var age: T = _ 3 } 4 5 def main(args: Array[String]): Unit = { 6 var a = new Cmx[String]("cmx") 7 println(a.name.getClass) 8 //class java.lang.String 9 var b = new Cmx[Int](123) 10 println(b.name.getClass) 11 //int 12 13 //样例类也可以 14 case class Cmx01[T](var name: T) 15 var c = Cmx01[Double](10.0) 16 println(c.name.getClass) 17 //double 18 }
2.泛型方法
1 def func[T](name: T) = { 2 println(name) 3 } 4 5 def func2[T](a: Array[T]) = { 6 a.foreach(println(_)) 7 } 8 9 def main(args: Array[String]): Unit = { 10 func[String]("cmx") 11 func[Int](1) 12 //cmx 13 //1 14 //赋值时[T]的类型 决定后面参数的类型 二者必须保持一致 15 func2[String](Array("1", "2")) 16 func2[Int](Array(1, 2, 3)) 17 }
3.泛型的上下界
上界:[T <: 类型] 或者是这个类型 或者 是这个类型的子类
下界:[T >: 类型] 或者是这个类型 或者 是这个类型父亲
1 class Cmx 2 3 class Cmx01 extends Cmx 4 5 //下界 6 def func[T >: Cmx01](name: T) = println(name) 7 8 //上界 9 def func1[T <: Cmx01](name: T) = println(name) 10 11 def main(args: Array[String]): Unit = { 12 //下界演示:只要时Cmx01或者其父类均可,但是依旧要保持前后的二者类型相同 13 func[Cmx](new Cmx) 14 func[Cmx01](new Cmx01) 15 //cmm_test.test2$Cmx@23223dd8 16 //cmm_test.test2$Cmx01@4ec6a292 17 18 //上界演示 19 func1[Cmx](new Cmx) 20 //直接报错 ,意为最大就是Cmx01 ,因为它是上界 21 //Error:(26, 10) type arguments [cmm_test.test2.Cmx] do not conform to method func1's type parameter bounds [T <: cmm_test.test2.Cmx01] 22 func1[Cmx01](new Cmx01) 23 //cmm_test.test2$Cmx01@1b40d5f0
七、柯里化
定义:柯里化(Currying) 将原来接受多个参数的方法转换为多个只接受一个参数的方法列表
格式案例:
1 def test(x:Int,y:Int):Unit = { 2 println(x+y) 3 } 4 //演变成单个参数的列表 5 def test(x:Int)(y:Int):Unit = { 6 println(x+y) 7 } 8 9 test(1)(2)
1 //格式:参数列表放在前面,后面的第二个参数是一个函数格式(函数名:(参数类型#与前面的类型保持一致)=>返回值类型) 2 def test(x: Int)(fun1: (Int) => Int) = { 3 fun1(x) 4 } 5 6 def main(args: Array[String]): Unit = { 7 //借用函数编程 调用函数 8 println(test(1)(_ + 11)) 9 //12 10 }
八、隐式转换
定义:为原本定义好的类,增加新的功能
1 //定义方法阶段:构造器的参数 类型必须时String 因为你要添加这个原始类的功能 2 class Text(var s: String) { 3 //这个方法就是我们要添加String类的新方法,名字即为方法 4 //方法自定义:参数可写可不写 扩展性大 5 def func() = { 6 println(s"${s}=>cmx") 7 } 8 } 9 10 //通过implicit 实装与String 11 //关键字imolicit 后的方法里的参数类型也要是String,后面的实例化 必须是定义阶段的类 12 implicit def func2(e: String) = new Text(e) 13 14 def main(args: Array[String]): Unit = { 15 //测试 16 var a: String = "hhh" 17 a.func() 18 //hhh=>cmx 19 }
1 //自定义的一个类 参数类型需是要添加方法的类 2 class RichFile(val f: File) { 3 def read() = { 4 //scala中的io操作读取文件并转化成字符串 5 Source.fromFile(f).mkString 6 } 7 } 8 9 //隐式转换实装 implicit 关键字 函数名 随意 参数名随意 参数类型 :要添加方法的类 10 //函数体:new 前面定义过的类然后将参数放进去 11 implicit def Cmx(f: File) = new RichFile(f) 12 13 def main(args: Array[String]): Unit = { 14 //文件自定义 路径要写对 盘符不区分大小写 15 //实例化File 对象 这时该对象就可以调用read的方法了 16 var f = new File("e:/1.txt") 17 val str = f.read() 18 println(str) 19 //ssss 20 }