vlambda博客
学习文章列表

scala语言----函数式编程(基础篇)

1. 概念说明


方法、函数、函数式编程、面向对象编程

1)scala中,方法和函数几乎可以等同(定义、使用、运行机制一样),只是函数的使用方式更加灵活。

object Method2Function { def main(args:Array[String]): Unit ={ val dog = new Dog println(dog.sum(10,20)) //方法转函数      val f1 = dog.sum _   // 格式:方法名 空格 下划线 println("f1 = " + f1) // f1 = <function2> 2表示两个形参 println("f1 = " + f1(20,30)) //函数 val f2 = (a:Int,b:Int) => a + b //val f2 = (a:Int,b:Int) => { a + b } 函数体 println("f2 = " + f2(2,3)) }}class Dog{ def sum(a:Int,b:Int): Int ={ a + b }}

2)在scala中,函数可以像变量一样,既可以作为函数的参数使用,也可以将函数赋值给一个变量,函数的创建无需依赖于类或者对象,而在java中,函数的创建要依赖于类、抽象类或接口。

3)面向对象编程是以对象为基础的编程方式。


2. 函数的定义

  def 函数名 ([参数名:参类型],...)[[:返回值类型] = ] {

      语句

      return 返回值

   }

1)[参数名:参数类型],...  :表示函数的输入(参数列表),可以没有。若有,多个参数使用逗号隔开。

2)函数可以有返回值,也可以没有。

3)返回值形式1:  :返回值类型 = 

4)返回值形式2:= 表示返回值类型不确定,使用类型推导完成

5)返回值形式3:     表示没有返回值,return不生效

6)若没有return,默认以执行到最后一行的结果作为返回值。

object FunctionDemo_01 { def main(args:Array[String]): Unit ={ println(getRes(10,20,'-')) } def getRes(a:Int,b:Int,oper:Char) = {//无返回值类型 if(oper == '+'){ a + b }else if(oper == '-'){ a - b }else{ null } }}


3. 函数注意事项

1)函数的形参列表可以是多个,若无形参,调用时可以不写()

object TestDemo{ def main(args:Array[String]):Unit = { def f1 = "Hello, world!" println(f1) }}def f1 = "Hello, world!"  等价于 def f1() = {"Hello, world!"}

2)形参列表和返回值列表的数据类型可以是值类型和引用类型

3)scala函数的形参默认是val的,因此不能在函数中进行修改

def f6(p1:String = "v1",p2:String){ println(p1+p2)}f6("v2")//报错f6(p2="v2")//指定覆盖某个默认值

4)递归函数未执行之前无法推断出结果类型,在使用时必须有明确的返回值类型。

5)scala支持可变参数,可变参数需要写在形参列表的最后

//支持0到多个参数def sum(args:Int*):Int = {} //args是一个集合,通过for循环可以访问到各个值def sum(n1:Int,args:Int*) = {}
object FunctionDemo_01 { def main(args:Array[String]): Unit ={ println(sum(10,20,30,40)) } def sum(n1:Int,args:Int*) :Int = { println("args.length"+ args.length) var s:Int = n1      for(i <- args)//通过for遍历可变参数 { s += i } s    }


4. 过程

将函数的返回类型为Unit的函数称之为过程,如果明确函数没有返回值,等号可以省略。

5. 惰性函数

惰性计算(尽可能延迟表达式求值)是许多函数式编程语言的特点。惰性集合在需要时提供其元素,无需预先计算他们,这带来了好处。首先,可以将耗时的计算推迟到绝对需要的时候。其次,可以创造无限个集合,只要他们继续收到请求,就会继续提供元素。

当函数返回值被声明为lazy时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数。在java的某些框架代码中称之为懒加载延迟加载)。

object FunctionDemo_01 { def main(args:Array[String]):Unit = { lazy val res = sum(10,20) println("............") println("res = " + res) } def sum(n1:Int,n2:Int): Int ={ println("sum()执行了........") return n1+n2 }}

结果:

............sum()执行了........res = 30

注意:1)lazy不能修饰var类型的变量。2)在声明变量时,加了lazy,变量值的分配也会推迟。lazy val i:Int = 10

6. 异常

scala提供try和catch块来处理异常。try块用于包含可能出错的代码,catch块用于处理try块中发生的异常。

Java异常:1)java语言按照try--catch--catch...--finally的方式来处理异常。2)不管有没有异常捕获,都会执行finally,因此通常在finally代码块中释放资源。在catch块捕获异常时,范围小的异常类放在范围大的异常类前面。

try{   int i = 0;   int b = 10;   int c = b / i;//除零异常}catch(Exception e){   e.printStackTrace();}finally{ System.out.println("java finally");}System.out.println("ok------继续执行-----");

scala异常:1)scala中只有一个catch。2)在catch中有多个case,每个case可以匹配一种异常 case ex:ArithmeticException   3)=> 关键符号,表示后面是对该异常的处理代码块。4)finally  最终要执行的

try{   val r = 10 / 0}catch{ case ex:ArithmeticException => {println("捕获除数为零的算数异常")}   case ex:Exception => println("捕获了异常")}finally{   println("scala finally...")}System.out.println("ok------继续执行-----")

scala异常处理小结

1)处理了异常,程序就不会异常终止。

2)scala的异常的工作机制和Java一样,但scala没有编译异常这个概念,异常都是在运行时捕获处理

3)用throw关键字,抛出一个异常对象。所有异常都是Throwable的子类型。throw表达式是有类型的,就是Nothing,因为Nothing是所有类型的子类型,所以throw表达式可以用在需要类型的地方。

def main(args:Array[String]){ val res = test() println(res.toString)}def test():Nothing = { throw new Exception("Wrong")}

4)在scala中,借助了模式匹配的思想来做异常的匹配

5)若有异常发生,catch子句是按照次序捕获的。因此在catch子句中,越具体的异常要越靠前。把范围大的异常写在前,scala也不会报错。

6)scala可以使用throws注释来声明异常

object ThrowsComment{ def main(args:Array[String]): Unit ={ f11() } @throws(classOf[NumberFormatException])//等同于java NumberFormatException.class def f11() = { "abc".toInt }}
val n = StdIn.readInt() //控制台输入