1. 基础语法
1.1. 注释
和java一样
// 我是单行注释
/*
我是多行注释
我是多行注释
*/
/**
* 我是文档注释
* 我是文档注释
*/
1.2. 语句
语句可以不以分号结尾
// 一条语句独占一行
println("Hello World!")
// 多条语句在一行
println("Hello World!"); println("Hello Scala!")
1.3. 打印输出
println("123","123")//同时输出多个字符串
1.4. 常量
val 常量名:常量类型 = 初始值
val max_num:Int = 100
1.5. 变量
var 变量名:变量类型 = 初始值
var minNum:Int = 1//Int可以省略,Scala会根据变量值自动匹配类型
官方推荐使用val
更安全
代码可读性更高
资源回收更快,方法执行完,val 所定义的常量就会被回收
1.6. 字符串
双引号、单引号、插值表达式
val|var 变量名 = "字符串"
val|var 变量名 = """
字符串1
字符串2
"""
val|var 变量名 = s"${变量|表达式}字符串"
val a = s"值为:${value}"
1.6.1. 惰性赋值
当有一些变量保存的数据较大时,且这些数据又不需要马上加载到 JVM 内存中,就可以使用惰性赋值来提高效率
lazy val 变量名 = 表达式
lazy val sql = """
12345
12345
12345
"""
//首次被使用该常量才会被加载到内存中。
println(sql)
1.7. 标识符
命名规则
- 支持大小写英文字母,数字,下划线_,美元符$;
- 不能数字开头;
- 不能使用关键字;
- 遵循见名知意。
- 支持"撇撇"。
val `worker.heartbeat.interval` = 3
命名规范
- 变量和方法:小驼峰,从第二个单词开始,每个单词的首字母大写。例如:maxSize、selectUserById。
- 类和特征(Trait):大驼峰,每个单词的首字母都大写。例如:UserController、WordCount。
- 包:全部小写,一般是公司或组织的域名反写,多级包之间用 . 隔开。例如:com.yjxxt.scala。
1.8. 数据类型
整型是Int不是Integer,Unit相当于java中的void。基本数据类型长度和java一致。
1.9. 类型转换
1.9.1. 自动类型转换(小转大)
val a:Int = 10
val b:Double = a+1.0
1.9.2. 强制类型转换(大转小".to类型")
使用".to类型"
val a:Double = 10.2
val b:Int = a.toInt
1.9.3. String类型转换(toString)
val a:String = "10"
val b:Int = a.toString
1.10. 键盘录入
- 导包: import scala.io.StdIn
- 调用方法:通过 StdIn.readXxx() 接收用户键盘录入的数据
import scala.io.StdIn
val userName = StdIn.readLine()
println(userName)
1.11. 运算符
和java一样
- 算术运算符
- 赋值运算符
- 关系运算符
- 逻辑运算符
1.12. 语句块
用{}括起来的
val result = {
println("这是一个语句块")
1+1
}
1.13. 流程控制
和java一样
- 顺序结构
- 选择结构
- 循环结构
三元表达式
val a = 10
val b:Boolean = if (a>10) true else false
1.14. 循环
格式
for (i <- 表达式|数组|集合) {
// 语句块(也叫循环体)
}
守卫
在for语句中添加if语句
for(i 1 to 10 if(i%2==0)) println(i)//输出2、4、6、8、10
//to代表【1,10】、Until代表区间【1,10)
yield生成器
将循环中的参数值返回到一个集合中
val result = for (i <- 1 to 10 if i % 2 == 0) yield i
break和continue
break
// 先导包
import scala.util.control.Breaks._
// 当 i == 5 时结束循环
breakable {
for (i <- 1 to 10) {
if (i == 5) break() else println(i)
}
}
continue
// 先导包
import scala.util.control.Breaks._
// 当 i == 5 时跳过当次循环,继续下一次
for (i <- 1 to 10) {
breakable {
if (i == 5) break() else println(i)
}
}
区别在于结束的代码范围。
1.15. 方法
在 Scala 中,方法传参默认是 val 类型,即不可变,这意味着你在方法体内部不能改变传入的参数。这和 Scala 的设计理念有关,Scala 遵循函数式编程理念,强调方法不应该有副作用。
1.15.1. 语法格式
def 方法名(参数名:参数类型, 参数名:参数类型, ...): [返回值类型] = {
// 语句块(方法体)
}
def addNum(a:Int, b:Int): Int = {
a + b
}//方法中最后一行产生的值就是返回值,可以省略return
1.15.2. 惰性方法
注意:lazy 只支持 val,不支持 var。
使用场景:
数据库连接,真正使用时才建立连接
提升程序的启动时间,将某些模块推迟执行
确保对象中的某些属性能优先初始化,对其他属性进行惰性化处理
// 定义方法
def addNum(a:Int, b:Int): Int = {
a + b
}
// 惰性加载
lazy val result = addNum(2, 3)
// 首次使用该值时,方法才会执行
println(result)
默认参数
def addNum(a:Int=1,b:Int=2):Int= a+b
val a = addNum
printLn(a) //返回3
带名参数
def addNum(a:Int=1,b:Int=2):Int= a+b
val a = addNum(b=5)
println(a) //返回6
变长参数
def add(a:Int*):Int={a.sum}
val a = add(1,2,3,4,5)
println(a)//返回15
方法调用
后缀调用法
Math.abs(-1)//对象.方法(参数)
中缀调用法
Math max (1, 2)//对象 方法 参数
花括号调用法
对象.方法{语句块}
Math.abs{-1}
Math.abs {
println("求绝对值")
-1
}
无括号调用法
方法是无参的
// 定义一个无参数的方法
def hello(): Unit = {
println("Hello World!")
}
// 调用方法
hello
1.16. 函数
在Scala函数式编程中,函数是一等公民,主要体现在:
- 函数可以存储在变量中
- 函数可以作为参数
- 函数可以作为返回值
函数式编程指的是方法的参数列表可以接收函数对象,函数式编程中的函数指的不是程序中的函数(方法),而是数学中的函数即映射关系,例如正弦函数 y=sin(x),x 和 y 的关系。
1.16.1. 定义函数
语法格式
// 因为函数是对象,所以函数有类型:(函数参数类型1, 函数参数类型2,...) => 函数返回值类型
val 函数名: (函数参数类型1, 函数参数类型2,...) => 函数返回值类型 = (参数名:参数类型, 参数名:参数类型, ...) => {
函数体
}
注意:
- 函数的本质就是引用类型,相当于 Java 中 new 出来的实例,所以函数是在堆内存中开辟空间;
- 函数的定义不需要使用 def 关键字,但定义的函数一定要有输入和返回值,没有返回值相当于返回的是 Unit;
- 函数不建议写 return 关键字,会报错,Scala 会使用函数体的最后一行代码作为返回值;
- 因为函数是对象,所以函数有类型,但函数类型可以省略,Scala 编译期可以自动推断类型。
val addNum:(a:Int,b:Int)=>(Int) = (a:Int,b:Int)=> a+b
//省略函数返回值
val addNum:(a:Int,b:Int)=>{a+b}
val result = addNum(10,20)
1.16.2. 方法和函数的区别
- 方法是隶属于类或者对象的,在运行时,它会被加载到 JVM 的方法区中
- 函数是一个对象,继承自 FunctionN,函数对象有 apply,curried,toString,tupled 这些方法,方法则没有。
1.16.3. 方法转换成函数
val|var 变量名=方法名_
def addNum(a:Int,b:Int):Int={
a+b
}
var c = addNum_
println(c(1,2))