Scala

文章目录


第二章 变量和数据类型

(一)注释

  • Scala 注释使用和 Java 完全一样。
  • 注释是一个程序员必须要具有的良好编程习惯。将自己的思想通过注释先整理出来,再
    用代码去体现

1、基本语法

1)单行注释://2)多行注释:/* */3)文档注释:/**
				*
				*/

2、案例

package net.cch.scala.day01

/**
 * 功能: 注释
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestNotes {
  def main(args: Array[String]): Unit = {
    //(1)单行注释://
    println("dalang")

    //(2)多行注释:/* */
    /*
    println("dalang")
    println("jinlian")
    */

    //(3)文档注释:/**
    //*
    //*/
    /**
     * println("qingge")
     * println("qingge")
     * p
     */
  }

}

(二)变量和常量

  • 常量:在程序执行的过程中,其值不会被改变的变量

1、基本语法

  • var 变量名 [: 变量类型] = 初始值 var i:Int = 10
  • val 常量名 [: 常量类型] = 初始值 val j:Int = 20
  • 注意:能用常量的地方不用变量

2、案例

  • var 变量
package net.cch.scala.day01

/**
 * 功能: var变量
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestVar {
  def main(args: Array[String]): Unit = {
    //(1)声明变量时,类型可以省略,编译器自动推导,即类型推导
    var age = 18
    age = 30
    //(2)类型确定后,就不能修改,说明 Scala 是强数据类型语言。
    // age = "tom" // 错误
    //(3)变量声明时,必须要有初始值
    // var name //错误

    //(4)在声明/定义一个变量时,可以使用 var 或者 val 来修饰,var 修饰 的变量可改变,val 修饰的变量不可改。
    var num1 = 10 // 可变
    val num2 = 20 // 不可变
    num1 = 30 // 正确
    //num2 = 100 //错误,因为 num2 是 val 修饰的
  }

}
  • val 常量
package net.cch.scala.day01

/**
 * 功能: val常量
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestVal {
  def main(args: Array[String]): Unit = {
    // p1 是 var 修饰的,p1 的属性可以变,而且 p1 本身也可以变
    var p1 = new Person()
    p1.name = "dalang"
    p1 = null
    // p2 是 val 修饰的,那么 p2 本身就不可变(即 p2 的内存地址不能变), 但是,p2 的属性是可以变,因为属性并没有用 val 修饰。
    val p2 = new Person()
    p2.name="jinlian"
    // p2 = null // 错误的,因为 p2 是 val 修饰的

  }
}
class Person{
  var name : String = "jinlian"
}

(三)标识符

  • Scala 对各种变量、方法、函数等命名时使用的字符序列称为标识符。即:凡是自己可
    以起名字的地方都叫标识符。

1、命名规则

1)以字母或者下划线开头,后接字母、数字、下划线
(2)以操作符开头,且只包含操作符(+ - * / # !等)
(3)用反引号`....`包括的任意字符串,即使是 Scala 关键字(39 个)也可以

(四)数据类型

  • 在Scala中,所有的值都有一个类型,包括数值和函数。如下图所示,说明了Scala的类型层次结构
    在这里插入图片描述

1、Any类型

  • Any是Scala类层次结构的根,也被称为超类或顶级类。Scala执行环境中的每个类都直接或间接地从该类继承。该类中定义了一些通用的方法,例如equals()、hashCode()和toString()。Any有两个直接子类:AnyVal和AnyRef。

2、AnyVal类型

AnyVal表示值类型,有9种预定义的值类型,它们是非空的Double、Float、Long、Int、Short、Byte、Char、Unit和Boolean。Unit是一个不包含任何信息的值类型,和Java语

3、AnyRef类型

  • AnyRef表示引用类型。所有非值类型都被定义为引用类型。Scala中的每个用户定义类型都是AnyRef的子类型。AnyRef对应于Java中的java.lang.Object。

4、整数类型(Byte、Short、Int、Long)

  • Scala 各整数类型有固定的表示范围和字段长度,不受具体操作的影响,以保证
    Scala 程序的可移植性。
(1)案例
package net.cch.scala.day01

/**
 * 功能: 整数类型
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestDataType {
  def main(args: Array[String]): Unit = {
    // 正确
    var n1:Byte = 127
    var n2:Byte = -128
    // 错误
    // var n3:Byte = 128
    // var n4:Byte = -129
	//Scala 的整型,默认为 Int 型,声明 Long 型,须后加‘l’或‘L’
    var n5 = 10
    println(n5)
    var n6 = 9223372036854775807L
    println(n6)

  }
}

5、浮点类型

  • Scala 的浮点类型可以表示一个小数,比如 123.4f,7.8,0.12 等等。
(1)案例
package net.cch.scala.day01

/**
 * 功能: 浮点类型
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestDateType1 {
  def main(args: Array[String]): Unit = {
    // 建议,在开发中需要高精度小数时,请选择 Double
    var n7 = 2.2345678912f
    var n8 = 2.2345678912
    println("n7=" + n7)
    println("n8=" + n8)

  }

}

  • 查看结果
    在这里插入图片描述

6、字符类型

(1)基本说明
  • 字符类型可以表示单个字符,字符类型是 Char。
(2)案例
package net.cch.scala.day01

/**
 * 功能: char类型
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestCharType {
  def main(args: Array[String]): Unit = {
    //(1)字符常量是用单引号 ' ' 括起来的单个字符。
    var c1: Char = 'a'
    println("c1=" + c1)
    //注意:这里涉及自动类型提升,其实编译器可以自定判断是否超出范围,
    //不过 idea 提示报错
    var c2:Char = 'a' + 1
    println(c2)

    //(2)\t :一个制表位,实现对齐的功能
    println("姓名\t 年龄")
    //(3)\n :换行符
    println("牛郎\n 织女")
    //(4)\\ :表示\
    println("D\\scala\\bin")
    //(5)\" :表示"
    println("大数据必学:\"学习scala\"")

  }

}

在这里插入图片描述

7、布尔类型

(1)基本说明
  • 布尔类型也叫 Boolean 类型,Booolean 类型数据只允许取值 true 和 false
  • boolean 类型占 1 个字节。
(2)案例
package net.cch.scala.day01

/**
 * 功能: Boolean类型
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestBooleanType {
  def main(args: Array[String]): Unit = {
    var isResult : Boolean = false
    var isResult2 : Boolean = true
  }

}

8、Unit 类型、Null 类型和 Nothing 类型

(1)基本说明
  • Unit:表示无值,和其他语言中 void 等同。用作不返回任何结果的方法的结果
    类型。Unit 只有一个实例值,写成()。
  • Null :null , Null 类型只有一个实例值 null
  • Nothing :Nothing 类型在 Scala 的类层级最低端;它是任何其他类型的子类型。
    当一个函数,我们确定没有正常的返回值,可以用 Nothing 来指定返回类
    型,这样有一个好处,就是我们可以把返回的值(异常)赋给其它的函数
    或者变量(兼容性)
(2)案例
  • Unit
package net.cch.scala.day01

/**
 * 功能: Unit类型
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestUnitType {
  def main(args: Array[String]): Unit = {
    def sayOk : Unit = {// unit 表示没有返回值,即 void

    }
    println(sayOk)
  }

}

  • Null
package net.cch.scala.day01

/**
 * 功能: Null类型
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestNullType {
  def main(args: Array[String]): Unit = {
    //null 可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型 (AnyVal)
    var cat = new Cat();
    cat = null // 正确
    var n1: Int = null // 错误
    println("n1:" + n1)
  }

}
class Cat{

}
  • Nothing
package net.cch.scala.day01

/**
 * 功能: Nothing类型
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestNothingType {
  def main(args: Array[String]): Unit = {
    def test() : Nothing={
      throw new Exception()
    }
    test
  }

}

第三章 运算符

(一)算术运算符

1、基本语法

在这里插入图片描述

2、案例

package net.cch.scala.day01

/**
 * 功能: 算术运算符
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestArithmetic {
  def main(args: Array[String]): Unit = {
    //(1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法 时,只保留整数部分而舍弃小数部分。
    var r1: Int = 10 / 3 // 3
    println("r1=" + r1)
    var r2: Double = 10 / 3 // 3.0
    println("r2=" + r2)
    var r3: Double = 10.0 / 3 // 3.3333
    println("r3=" + r3)
    println("r3=" + r3.formatted("%.2f")) // 含义:保留小数点 2位,使用四舍五入
    //(2)对一个数取模 a%b,和 Java 的取模规则一样。
    var r4 = 10 % 3 // 1
    println("r4=" + r4)

  }
}

(二)关系运算符

1、基本语法

在这里插入图片描述

2、案例

package net.cch.scala.day01

/**
 * 功能: 关系运算符
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestRelation {
  def main(args: Array[String]): Unit = {
    // 测试:>、>=、<=、<、==、!=
    var a: Int = 2
    var b: Int = 1
    println(a > b) // true
    println(a >= b) // true
    println(a <= b) // false
    println(a < b) // false
    println("a==b" + (a == b)) // false
    println(a != b) // true
  }
}

在这里插入图片描述

(三)逻辑运算符

1、基本语法

在这里插入图片描述

package net.cch.scala.day01

/**
 * 功能: 逻辑运算符
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestLogic {
  def main(args: Array[String]): Unit = {
    // 测试:&&、||、!
    var a = true
    var b = false
    println("a&&b=" + (a && b)) // a&&b=false
    println("a||b=" + (a || b)) // a||b=true
    println("!(a&&b)=" + (!(a && b))) // !(a&&b)=true
  }

}

在这里插入图片描述

(四)赋值运算符

1、基本语法

在这里插入图片描述

2、案例

package net.cch.scala.day01

/**
 * 功能: 赋值运算符
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestAssignment {
  def main(args: Array[String]): Unit = {
    var r1 = 10

    r1 += 1 // 没有++
    r1 -= 2 // 没有--

  }
}

(五) 位运算符

1、基本语法

在这里插入图片描述

2、案例

package net.cch.scala.day02

/**
 * 功能: 位运算
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestPosition {
  def main(args: Array[String]): Unit = {
    // 测试:1000 << 1 =>10000
    var n1 :Int =8
    n1 = n1 << 1
    println(n1)

  }

}

第四章 流程控制

(一)分支控制if-else

  • 让程序有选择的的执行,分支控制有三种:单分支、双分支、多分支

1、单分支

(1)基本语法
if (条件表达式) {
执行代码块
}
(2) 案例
package net.cch.scala.day02

import scala.io.StdIn

/**
 * 功能: 单分支
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestIf_else01 {
  def main(args: Array[String]): Unit = {
    //需求:输入人的年龄,如果该同志的年龄小于 18 岁,则输出“童年”
    println("input age:")
    var age = StdIn.readShort()
    if (age < 18){
      println("童年")
    }
  }

}

在这里插入图片描述

2、双分支

(1)基本语法
if (条件表达式) {
执行代码块 1
} else {
执行代码块 2
}
(2) 案例
package net.cch.scala.day02

import scala.io.StdIn

/**
 * 功能: 双分支
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestIfElse02 {
  def main(args: Array[String]): Unit = {
    //需求:输入年龄,如果年龄小于 18 岁,则输出“童年”。否则,输出“成年”。
    println("input age:")
    var age = StdIn.readShort()
    if (age < 18){
      println("童年")
    }else{
      println("成年")
    }

  }

}

3、多分支

(1)基本语法
if (条件表达式 1) {
执行代码块 1
}
else if (条件表达式 2) {
执行代码块 2
}
 ……
else {
执行代码块 n
}
(2) 实操
package net.cch.scala.day02

import scala.io.StdIn

/**
 * 功能: 多分支
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestIfElse03 {
  def main(args: Array[String]): Unit = {
    //需求 1:需求:输入年龄,如果年龄小于 18 岁,则输出“童年”。如果年龄大于等于 18 且小于等于 30,则输出“中年”,否则,输出“老年”。
    println("input age")
    var age = StdIn.readInt()
    if (age < 18){
      println("童年")
    }else if(age>=18 && age<30){
      println("中年")
    }else{
      println("老年")
    }

  }
}

在这里插入图片描述

(二) for循环

  • Scala 也为 for 循环这一常见的控制结构提供了非常多的特性,这些 for 循环的特性被称
    为 for 推导式或 for 表达式。
    在这里插入图片描述

1、范围数据循环(To)

(1)基本语法
for(i <- 1 to 3){
 print(i + " ")
}
println()
(2) 案例
package net.cch.scala.day02

import sun.applet.Main

/**
 * 功能: for循环
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestFor01 {
  def main(args: Array[String]): Unit = {
    for(i <- 1 to 5){
      println("Hello World"+i)
    }
  }

}

在这里插入图片描述

2、范围数据循环(Until)

(1)基本语法
for(i <- 1 until 3) {
 print(i + " ")
}
println()
(2)案例
package net.cch.scala.day02

/**
 * 功能: Until
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestFor02 {
  def main(args: Array[String]): Unit = {
    for(i <- 1 until 5 + 1){
      println("hello scala" + i)
    }
  }

}

在这里插入图片描述

3、循环守卫

(1)基本语法
for(i <- 1 to 3 if i != 2) {
 print(i + " ")
}
println()
  • 循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为 true 则进入循环
    体内部,为 false 则跳过,类似于 continue。

  • 上面的代码等价

for (i <- 1 to 3){
if (i != 2) {
print(i + " ")
}
}
(2)案例
  • 需求:输出 1 到 5 中,不等于 3 的值
package net.cch.scala.day03

/**
 * 功能: 循环守卫
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestFor {
  def main(args: Array[String]): Unit = {
    for (i <- 1 to 5 if i != 3) {
      println(i + "张三")
    }
  }

}

在这里插入图片描述

4、 循环步长

(1)基本语法
for (i <- 1 to 10 by 2) {
 println("i=" + i)
}
  • 说明:by表示步长
(2)实操
  • 需求:输出 1 到 10 以内的所有奇数
package net.cch.scala.day03

/**
 * 功能: 循环步长
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestFor1 {
  def main(args: Array[String]): Unit = {
    for (i <- 1 to 10 by 2) {
      println("i=" + i)
    }

  }

}

在这里插入图片描述

5、嵌套循环

(1)基本语法
for(i <- 1 to 3; j <- 1 to 3) {
 println(" i =" + i + " j = " + j)
}
  • 说明:没有关键字,所以范围后一定要加;来隔断逻辑
(2)基本语法
  • 等价于上面的代码
for (i <- 1 to 3) {
 for (j <- 1 to 3) {
 println("i =" + i + " j=" + j)
 }
}

6、引入变量

(1)基本语法
for(i <- 1 to 3; j = 4 - i) {
 println("i=" + i + " j=" + j)
}
  • for 推导式一行中有多个表达式时,所以要加 ; 来隔断逻辑
  • for 推导式有一个不成文的约定:当 for 推导式仅包含单一表达式时使用圆括号,
    当包含多个表达式时,一般每行一个表达式,并用花括号代替圆括号,如下
for {
 i <- 1 to 3
j = 4 - i
} {
 println("i=" + i + " j=" + j)
}
(2)案例
  • 上面的代码等价于
for (i <- 1 to 3) {
 var j = 4 - i
 println("i=" + i + " j=" + j)
}

7、循环返回值

(1)基本语法
val res = for(i <- 1 to 10) yield i
println(res)
  • 将遍历过程中处理的结果返回到一个新 Vector 集合中,使用 yield 关键字。
(2)实操
  • 需求:将原数据中所有值乘以 2,并把数据返回到一个新的集合中。
package net.cch.scala.day03

/**
 * 功能: 循环返回值
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestFor2 {
  def main(args: Array[String]): Unit = {
    var res = for(i <-1 to 10) yield {
      i * 2
    }
    println(res)
  }

}

在这里插入图片描述

8、倒序打印

(1)如果想倒序打印一组数据,可以用 reverse。
(2)实操:
  • 需求:倒序打印 10 到 1
package net.cch.scala.day03

import scala.language.postfixOps

/**
 * 功能: 倒序打印
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestFor3 {
  def main(args: Array[String]): Unit = {
    for(i <- 1 to 10 reverse){
      println(i)
    }
  }

}

(三)While循环控制

1、基本语法

循环变量初始化
while (循环条件) {
 循环体(语句)
 循环变量迭代
}
  • 循环条件是返回一个布尔值的表达式
  • while 循环是先判断再执行语句
  • 与 for 语句不同,while 语句没有返回值,即整个 while 语句的结果是 Unit 类型()
  • 因为 while 中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免
    的使用变量,而变量需要声明在 while 循环的外部,那么就等同于循环的内部对外部的变量
    造成了影响,所以不推荐使用,而是推荐使用 for 循环。

2、案例

  • 需求:输出10句“I LOVE YOU”
package net.cch.scala.day03

/**
 * 功能: While循环
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestWhile {
  def main(args: Array[String]): Unit = {
    var i = 0
    while (i < 10) {
      println("I LOVE YOU" + i)
      i += 1
    }
  }
}

(四)do…while 循环控制

(1)基本语法

循环变量初始化;
 do{
	循环体(语句)
 	循环变量迭代
 } while(循环条件
  • 循环条件是返回一个布尔值的表达式
  • do…while 循环是先执行,再判断

(2)案例

  • 需求:输出 10 句 “I LOVE YOU”
package net.cch.scala.day03

/**
 * 功能: 循环控制
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestDoWhile {
  def main(args: Array[String]): Unit = {
    var i = 0
    do {
      println("宋宋,喜欢海狗人参丸" + i)
      i += 1
    } while (i < 10)
  }

}

(五)循环中断

1、基本说明

  • Scala 内置控制结构特地去掉了 break 和 continue,是为了更好的适应函数式编程,推
    荐使用函数式的风格解决break和continue的功能,而不是一个关键字。Scala中使用breakable
    控制结构来实现 break 和 continue 功能

2、实操

  • 需求一:采用异常的方式退出循环
package net.cch.scala.day03

/**
 * 功能: 控制循环
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestBreak {
  def main(args: Array[String]): Unit = {
    try {
      for (elem <- 1 to 10) {
        println(elem)
        if (elem == 5) throw new RuntimeException
      }
    } catch {
      case e =>
    }
    println("正常结束循环")
  }

}

在这里插入图片描述

  • 需求二:采用异常的方式退出循环
package net.cch.scala.day03

import scala.util.control.Breaks

/**
 * 功能: 控制循环
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestBreakS {
  def main(args: Array[String]): Unit = {
    Breaks.breakable(
      for (elem <- 1 to 10) {
        println(elem)
        if (elem == 5) Breaks.break()
      }
    )
    println("正常结束循环")

  }

}

在这里插入图片描述

  • 需求 3:对 break 进行省略
package net.cch.scala.day03
import scala.util.control.Breaks._
/**
 * 功能: 控制循环
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestBreak1 {
  def main(args: Array[String]): Unit = {
    breakable {
      for (elem <- 1 to 10) {
        println(elem)
        if (elem == 5) break
      }
    }
    println("正常结束循环")
  }
}

在这里插入图片描述

  • 需求 4:循环遍历 10 以内的所有数据,奇数打印,偶数跳过(continue)
package net.cch.scala.day03

/**
 * 功能: 控制循环
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestBreak2 {
  def main(args: Array[String]): Unit = {
    for (elem <- 1 to 10) {
      if (elem % 2 == 1) {
        println(elem)
      } else {
        println("continue")
      }
    }
  }
}

在这里插入图片描述

(六)多重循环

1、基本说明

  • 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for,while,do…while
    均可以作为外层循环和内层循环。【建议一般使用两层,最多不要超过 3 层】
  • 设外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n 次。

2、打印九九乘法表

package net.cch.scala.day03

/**
 * 功能: 打印九九乘法表
 * 作者: 陈春宏
 * 时间: 2022年06月10日
 */
object TestWhile1 {
  def main(args: Array[String]): Unit = {
    for(i<- 1 to 9){
      for(j <- 1 to i){
        print(j + "*" + i + "=" + (i * j)+ "\t")
      }
      println()
    }
  }
}

在这里插入图片描述

第五章 函数式编程

(1)面向对象编程
  • 解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。
  • 对象:用户
  • 行为:登录、连接 JDBC、读取数据库
  • 属性:用户名、密码
  • Scala 语言是一个完全面向对象编程语言。万物皆对象
  • 对象的本质:对数据和行为的一个封装
(2)函数式编程
  • 解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用
    这些封装好的步骤,解决问题。
  • 例如:请求->用户名、密码->连接 JDBC->读取数据库
  • Scala 语言是一个完全函数式编程语言。万物皆函数。
  • 函数的本质:函数可以当做一个值进行传递
(3)在 Scala 中函数式编程和面向对象编程完美融合在一起了

一、函数基础

1、函数基本语法

(1)基本语法

在这里插入图片描述

(2)实操
  • 需求:定义一个函数,实现将传入的名称打印出来。
package net.cch.scala.day04

/**
 * 功能: 函数基本语法
 * 作者: 陈春宏
 * 时间: 2022/6/20 9:43
 */
object TestFunction {
  def main(args: Array[String]): Unit = {
    // (1)函数定义
    def f(arg: String): Unit = {
      println(arg)
    }
    // (2)函数调用
    // 函数名(参数)
    f("hello world")
    }

}

在这里插入图片描述

2、函数和方法的区别

(1)核心概念
  • 为完成某一功能的程序语句的集合,称为函数。
  • 类中的函数称之方法。
(2)实操
  • Scala 语言可以在任何的语法结构中声明任何的语法
  • 函数没有重载和重写的概念;方法可以进行重载和重写
  • Scala 中函数可以嵌套定义
package net.cch.scala.day04

/**
 * 功能: 函数的嵌套
 * 作者: 陈春宏
 * 时间: 2022/6/20 9:48
 */
package net.cch.scala.day04

/**
 * 功能: 函数的嵌套
 * 作者: 陈春宏
 * 时间: 2022/6/20 9:48
 */
object TestFunction1 {
  // (2)方法可以进行重载和重写,程序可以执行
  def main(): Unit = {
  }

  def main(args: Array[String]): Unit = {
    // (1)Scala 语言可以在任何的语法结构中声明任何的语法
    import java.util.Date
    new Date()

    // (2)函数没有重载和重写的概念,程序报错
    def test(): Unit = {
      println("无参,无返回值")
    }

    test()

//    def test(name: String): Unit = {
//      println()
//    }

    //(3)Scala 中函数可以嵌套定义
    def test2(): Unit = {

      def test3(name: String): Unit = {
        println("函数可以嵌套定义")
      }
    }
  }
}

在这里插入图片描述

3、函数定义

(1)函数定义
  • 函数 1:无参,无返回值
  • 函数 2:无参,有返回值
  • 函数 3:有参,无返回值
  • 函数 4:有参,有返回值
  • 函数 5:多参,无返回值
  • 函数 6:多参,有返回值
(2)案例
package net.cch.scala.day04

/**
 * 功能: 函数定义
 * 作者: 陈春宏
 * 时间: 2022/6/20 9:53
 */
object TestFunctionDeclare {
  def main(args: Array[String]): Unit = {
    // 函数 1:无参,无返回值
    def test1(): Unit ={
      println("无参,无返回值")
    }
    test1()
    // 函数 2:无参,有返回值
    def test2():String={
      return "无参,有返回值"
    }
    println(test2())
    // 函数 3:有参,无返回值
    def test3(s:String):Unit={
      println(s)
    }
    test3("jinlian")

    // 函数 4:有参,有返回值
    def test4(s:String):String={
      return s+"有参,有返回值"
    }
    println(test4("hello "))
    // 函数 5:多参,无返回值
    def test5(name:String, age:Int):Unit={
      println(s"$name, $age")
    }
    test5("dalang",40)
  }

}

在这里插入图片描述

4、函数参数

(1)案例实操
  • 可变参数
  • 如果参数列表中存在多个参数,那么可变参数一般放置在最后
  • 参数默认值,一般将有默认值的参数放置在参数列表的后面
  • 带名参数
package net.cch.scala.day04

/**
 * 功能: 函数参数
 * 作者: 陈春宏
 * 时间: 2022/6/20 11:06
 */
object TestFunction2 {
  def main(args: Array[String]): Unit = {
    // (1)可变参数
    def test( s : String* ): Unit = {
      println(s)
    }
    // 有输入参数:输出 Array
    test("Hello", "Scala")
    // 无输入参数:输出 List()
    test()
    // (2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
    def test2( name : String, s: String* ): Unit = {
      println(name + "," + s)
    }
    test2("jinlian", "dalang")
    // (3)参数默认值
    def test3( name : String, age : Int = 30 ): Unit = {
      println(s"$name, $age")
    }
    // 如果参数传递了值,那么会覆盖默认值
    test3("jinlian", 20)
    // 如果参数有默认值,在调用的时候,可以省略这个参数
    test3("dalang")
    // 一般情况下,将有默认值的参数放置在参数列表的后面
    def test4( sex : String = "男", name : String ): Unit = {
      println(s"$name, $sex")
    }
    // Scala 函数中参数传递是,从左到右
    //test4("wusong")
    //(4)带名参数
    test4(name="ximenqing")

    }

}

在这里插入图片描述

5、函数至简原则(重点)

  • 函数至简原则:能省则省
(1)至简原则细节
(1)return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
(2)如果函数体只有一行代码,可以省略花括号
(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
(4)如果有 return,则不能省略返回值类型,必须指定
(5)如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
(6)Scala 如果期望是无返回值类型,可以省略等号
(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
(2)案例
package net.cch.scala.day04

/**
 * 功能: 函数至简原则
 * 作者: 陈春宏
 * 时间: 2022/6/20 11:12
 */
object TestFunction3 {
  def main(args: Array[String]): Unit = {
    // (0)函数标准写法
    def f(s: String): String = {
      return s + " jinlian"
    }

    println(f("Hello"))

    // 至简原则:能省则省
    //(1) return 可以省略,Scala 会使用函数体的最后一行代码作为返回值
    def f1(s: String): String = {
      s + " jinlian"
    }

    println(f1("Hello"))

    //(2)如果函数体只有一行代码,可以省略花括号
    def f2(s: String): String = s + " jinlian"

    //(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起 省略)
    def f3(s: String) = s + " jinlian"

    println(f3("Hello3"))

    //(4)如果有 return,则不能省略返回值类型,必须指定。
    def f4(): String = {
      return "ximenqing4"
    }

    println(f4())

    //(5)如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
    def f5(): Unit = {
      return "dalang5"
    }

    println(f5())

    //(6)Scala 如果期望是无返回值类型,可以省略等号
    // 将无返回值的函数称之为过程
//    def f6() {
//      "dalang6"
//    }

//    println(f6())

    //(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
    def f7() = "dalang7"

    println(f7())

    def f8 = "dalang"
    //println(f8())
    println(f8)

    //(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
    def f9 = (x: String) => {
      println("wusong")
    }

    def f10(f: String => Unit) = {
      f("")
    }

    f10(f9)
    println(f10((x: String) => {
      println("wusong")
    }))

  }
}

在这里插入图片描述

(二)函数高级

1、高阶函数

  • 在 Scala 中,函数是一等公民。怎么体现的呢?
  • 对于一个函数我们可以:定义函数、调用函数
package net.cch.scala.day04

/**
 * 功能: 高级函数
 * 作者: 陈春宏
 * 时间: 2022/6/20 11:17
 */
object TestFunction4 {
  def main(args: Array[String]): Unit = {
    // 调用函数
    foo()
  }
  // 定义函数
  def foo():Unit = {
    println("foo ...")
  }

}

(1)函数可以作为值进行传递
package net.cch.scala.day04

/**
 * 功能: 函数作为值传递
 * 作者: 陈春宏
 * 时间: 2022/6/20 11:20
 */
object TestFunction5 {
  def main(args: Array[String]): Unit = {
    //(1)调用 foo 函数,把返回值给变量 f
    //val f = foo
    val f = foo()
    println(f)


    val f1 = foo _
    foo()
    f1()
    //(3)如果明确变量类型,那么不使用下划线也可以将函数作为整体传递给变量
    var f2:()=>Int = foo
  }
  def foo():Int = {
    println("foo...")
    1

  }
}

在这里插入图片描述

(2)函数可以作为参数进行传递
package net.cch.scala.day04

/**
 * 功能: 函数作为参数传递
 * 作者: 陈春宏
 * 时间: 2022/6/20 11:23
 */
object TestFunction6 {
  def main(args: Array[String]): Unit = {
    // (1)定义一个函数,函数参数还是一个函数签名;f 表示函数名称;(Int,Int) 表示输入两个 Int 参数;Int 表示函数返回值
    def f1(f: (Int, Int) => Int): Int = {
      f(2, 4)
    }

    // (2)定义一个函数,参数和返回值类型和 f1 的输入参数一致
    def add(a: Int, b: Int): Int = a + b

    // (3)将 add 函数作为参数传递给 f1 函数,如果能够推断出来不是调用,可以省略
    println(f1(add))
    println(f1(add _))
    //可以传递匿名函数

  }

}

在这里插入图片描述

(3)函数可以作为函数返回值返回
package net.cch.scala.day04

/**
 * 功能: 函数作为返回值返回
 * 作者: 陈春宏
 * 时间: 2022/6/20 11:25
 */
object TestFunction7 {
  def main(args: Array[String]): Unit = {
    def f1() = {
      def f2() = {
      }
      f2 _
    }
    val f = f1()
    // 因为 f1 函数的返回值依然为函数,所以可以变量 f 可以作为函数继续调用
    f()
    // 上面的代码可以简化为
    f1()()

  }

}

2、匿名函数

(1)说明
  • 没有名字的函数就是匿名函数。
(x:Int)=>{函数体}
  • x:表示输入参数类型;Int:表示输入参数类型;函数体:表示具体代码逻辑
(2)实操
  • 需求一:传递的函数有一个参数

  • 传递匿名函数至简原则:
    (1)参数的类型可以省略,会根据形参进行自动的推导
    (2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参
    数超过 1 的永远不能省略圆括号。
    (3)匿名函数如果只有一行,则大括号也可以省略
    (4)如果参数只出现一次,则参数省略且后面参数可以用_代替

package net.cch.scala.day04

/**
 * 功能: 匿名函数
 * 作者: 陈春宏
 * 时间: 2022/6/20 16:54
 */
object TestAnonymousFunction {
  def main(args: Array[String]): Unit = {
    //(1)定义一个函数:参数包含数据和逻辑函数
    def operation(arr:Array[Int],op:Int =>Int) = {
      for(elem <- arr) yield op (elem)
    }
    // (2)定义逻辑函数
    def op(ele: Int): Int = {
      ele + 1
    }
    // (3)标准函数调用
    val arr = operation(Array(1, 2, 3, 4), op)
    println(arr.mkString(","))
    // (4)采用匿名函数
    val arr1 = operation(Array(1, 2, 3, 4), (ele: Int) => {
      ele + 1
    })
    println(arr1.mkString(","))
    // (4.1)参数的类型可以省略,会根据形参进行自动的推导;
    val arr2 = operation(Array(1, 2, 3, 4), (ele) => {
      ele + 1
    })
    println(arr2.mkString(","))
    // (4.2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过 1 的永远不能省略圆括号。
    val arr3 = operation(Array(1, 2, 3, 4), ele => {
      ele + 1
    })
    println(arr3.mkString(","))
    // (4.3) 匿名函数如果只有一行,则大括号也可以省略
    val arr4 = operation(Array(1, 2, 3, 4), ele => ele + 1)
    println(arr4.mkString(","))
    //(4.4)如果参数只出现一次,则参数省略且后面参数可以用_代替
    val arr5 = operation(Array(1, 2, 3, 4), _ + 1)
    println(arr5.mkString(","))
  }
}

  • 需求 2:传递的函数有两个参数
package net.cch.scala.day04

/**
 * 功能: 匿名函数
 * 作者: 陈春宏
 * 时间: 2022/6/20 16:54
 */
object TestAnonymousFunction01 {
  def main(args: Array[String]): Unit = {
    def calculator(a: Int, b: Int, op: (Int, Int) => Int): Int = {
      op(a, b)
    }
    // (1)标准版
    println(calculator(2, 3, (x: Int, y: Int) => {
      x + y
    }))
    // (2)如果只有一行,则大括号也可以省略
    println(calculator(2, 3, (x: Int, y: Int) => x + y))
    // (3)参数的类型可以省略,会根据形参进行自动的推导;
    println(calculator(2, 3, (x, y) => x + y))
    // (4)如果参数只出现一次,则参数省略且后面参数可以用_代替
    println(calculator(2, 3, _ + _))
  }
}

3、高阶函数案例

  • 需求:模拟 Map 映射、Filter 过滤、Reduce 聚合
package net.cch.scala.day04

import scala.collection.mutable.ArrayBuffer

/**
 * 功能: 高阶函数案例
 * 作者: 陈春宏
 * 时间: 2022/6/20 16:54
 */
object TestAnonymousFunction02 {
  def main(args: Array[String]): Unit = {
    // (1) map 映射
    def map(arr: Array[Int], op: Int => Int) = {
      for (elem <- arr) yield op(elem)
    }
    val arr = map(Array(1, 2, 3, 4), (x: Int) => {
      x * x
    })
    println(arr.mkString(","))
    // (2)filter 过滤。有参数,且参数再后面只使用一次,则参数省略且后面参数用_表示
    def filter(arr:Array[Int],op:Int =>Boolean) ={
      var arr1:ArrayBuffer[Int] = ArrayBuffer[Int]()
      for(elem <- arr if op(elem)){
        arr1.append(elem)
      }
      arr1.toArray
    }
    var arr1 = filter(Array(1, 2, 3, 4), _ % 2 == 1)
    println(arr1.mkString(","))
    // (3)reduce 聚合。有多个参数,且每个参数再后面只使用一次,则参数省略且后面参数用_表示,第 n 个_代表第 n 个参数
    def reduce(arr: Array[Int], op: (Int, Int) => Int) = {
      var init: Int = arr(0)
      for (elem <- 1 until arr.length) {
        init = op(init, elem)
      }
      init
    }
    //val arr2 = reduce(Array(1, 2, 3, 4), (x, y) => x * y)
    val arr2 = reduce(Array(1, 2, 3, 4), _ * _)
    println(arr2)
    }
}

4、函数柯里化&闭包

  • 闭包:函数式编程的标配
(1)说明
  • 闭包:如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的
    环境,称为闭包
  • 函数柯里化:把一个参数列表的多个参数,变成多个参数列表。
(2)案例
package net.cch.scala.day04

/**
 * 功能: 函数闭包
 * 作者: 陈春宏
 * 时间: 2022/6/20 17:08
 */
object TestFunctionClosure {
  def main(args: Array[String]): Unit = {
    def f1()={
      var a:Int = 10
      def f2(b:Int)={
        a + b
      }
      f2 _
    }
    // 在调用时,f1 函数执行完毕后,局部变量 a 应该随着栈空间释放掉
    val f = f1()
    // 但是在此处,变量 a 其实并没有释放,而是包含在了 f2 函数的内部,形成了闭合的效果
    println(f(3))

    println(f1()(3))
    // 函数柯里化,其实就是将复杂的参数逻辑变得简单化,函数柯里化一定存在闭包
    def f3()(b:Int)={
      a + b
    }
    println(f3()(3))
  }

}

5、递归

(1)说明
  • 一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用
(2)案例
package net.cch.scala.day04

/**
 * 功能: 递归
 * 作者: 陈春宏
 * 时间: 2022/6/20 17:13
 */
object TestRecursion {
  def main(args: Array[String]): Unit = {
    // 阶乘
    // 递归算法
    // 1) 方法调用自身
    // 2) 方法必须要有跳出的逻辑
    // 3) 方法调用自身时,传递的参数应该有规律
    // 4) scala 中的递归必须声明函数返回值类型
    println(test(5))
  }
  def test(i : Int) : Int = {
    if (i == 1) {
      1
    } else {
      i * test(i - 1)
    }
  }
}

6、控制抽象

(1)值调用:把计算后的值传递过去
package net.cch.scala.day04

/**
 * 功能: 控制抽象
 * 作者: 陈春宏
 * 时间: 2022/6/20
 */
object ControlAbstraction {
  def main(args: Array[String]): Unit = {
    def f = ()=>{
      println("f...")
      10
    }
    foo(f())
  }
  def foo(a: Int):Unit = {
    println(a)
    println(a)

    }

}

(2)名调用:把代码传递过去
package net.cch.scala.day04

/**
 * 功能: 名调用
 * 作者: 陈春宏
 * 时间: 2022/6/20 17:49
 */
object TestControl {
  def main(args: Array[String]): Unit = {
    def f = ()=>{
      println("f...")
      10
    }
    foo(f())
  }
  //def foo(a: Int):Unit = {
  def foo(a: =>Int):Unit = {//注意这里变量 a 没有小括号了
    println(a)
    println(a)
  }

}

(3)案例
package net.cch.scala.day04

/**
 * 功能: 
 * 作者: 陈春宏
 * 时间: 2022/6/20 17:51
 */
object TestFunction8 {
  def main(args: Array[String]): Unit = {
    // (1)传递代码块
    foo({
      println("aaa")
    })
    // (2)小括号可以省略
    foo{
      println("aaa")
    }
    def foo(a: =>Unit):Unit = {
      println(a)
      println(a)
    }
  }

}

  • 自定义一个while循环
package net.cch.scala.day04

/**
 * 功能: 抽象控制
 * 作者: 陈春宏
 * 时间: 2022/6/20 17:52
 */
object TestFunction9 {
  def main(args: Array[String]): Unit = {
    var i:Int = 1
    myWhile(i <= 10){
      println(i)
      i +=1
    }
  }
  def myWhile(condition: =>Boolean)(op: =>Unit):Unit={
    if (condition){
      op
      myWhile(condition)(op)
    }
  }

}

7、惰性加载

(1)说明
  • 当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到我们首次对此取值,该函
    数才会执行。这种函数我们称之为惰性函数。
(2)案例
package net.cch.scala.day04

/**
 * 功能: 惰性加载
 * 作者: 陈春宏
 * 时间: 2022/6/20
 */
object TestFunction01 {
  def main(args: Array[String]): Unit = {
    lazy val res = sum(10, 30)
    println("----------------")
    println("res=" + res)
  }
  def sum(n1: Int, n2: Int): Int = {
    println("sum 被执行。。。")
    return n1 + n2
  }

}

在这里插入图片描述

  • 注意:lazy 不能修饰 var 类型的变量

第六章 面向对象

第七章 集合

第八章 模式匹配

第九章 异常

第十章 隐式转换

第十一章 泛型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值