Skip to content

第二章 Scala基本语法 v1.0 ​

第一部分 数据类型 ​

一、变量与常量 ​

1.不可变变量(val)-推荐使用 ​

使用val定义基本数据类型时,相当于加上了final修饰,值(引用)不可变,可以使用val重新定义

基本语法:val value[:手动指定类型] = "初值" //声明变量时,可不指定类型,编译器会自动推断

2.懒加载不可变变量(lazy val) ​

只有val修饰的变量才能被lazy修饰,使用lazy定义变量后,只有在调用该变量时才会实例化这个变量的值

基本语法:lazy val value[:手动指定类型] = "初值"

3.可变变量(var) ​

var修饰的变量,内容和引用都可变,一般只有当真正需要改变状态时,才使用var

基本语法:var value[:手动指定类型] = "初值"

4.字符串定义 ​

  1. 使用双引号
scala
val/var str = "str"
  1. 使用三引号
scala
val/var str = """str
str"""
  1. 使用插值表达式
scala
val str = "str"
val/var str = s"str=${str}"  //使用${}作为占位符

二、数据类型 ​

1.基本数据类型 ​

88dfd129-45ac-40ba-a90f-5a649795a95e.png

2.类型转换 ​

  1. 自动类型转换

示例:val x: Long = 987654321 //将987654321赋值给Long类型的x,会进行自动类型转换

  1. 强制类型转换

示例:int a = (int) 100.00 //将100.00强制类型转换为int赋值给a

  1. 类型判定

示例:i1.isInstanceOf[Int] //判定i1是否为int类型(或其子类)

  1. 类型转换

示例:i2.asInstanceOf[类型] //将对象i2转换为指定类型

第二部分 控制语句 ​

一、选择结构 ​

1.基本语法 ​

scala
if (条件表达式1) {	
  //执行代码块1  
}   
else if (条件表达式2) {	
  //执行代码块2
}
……      
else {
  //执行代码块n 
}

2.注意要点 ​

  1. Scala中,条件表达式是有返回值的
  2. Scala中没有三元表达式,使用if(条件表达式) <真结果> else <假结果>代替三元表达式

二、循环结构 ​

1.for循环-基本语法 ​

scala
for(i <- 表达式[; j <- 表达式; ... ]){  //for语句中可以有多个生成器
  //循环体
}
//在for表达式中可以添加if判定语句,该if判断称之为守卫
for(i <- 表达式; if 过滤条件]){ 
  //循环体
}

i <- 表达式 称为生成器,可从集合中取出每个元素,或创建迭代器,常用的两种方式为:to和until

区别:i <- i to j //包括i和j,i <- i until j //包括i,不包括j

2.for循环-yield循环体 ​

在Scala中,yield的主要作用是记住每次迭代中的有关值,并逐一存入到一个数组中

scala
val retVal = for {子句} yield {变量或表达式} 
val a = for(i <- 1 to 10) yield i*10  //示例:生成10、20、...、100的集合

3.do-while循环 ​

基本语法:while(条件语句){表达式}

4.while循环 ​

基本语法:do{表达式}while(条件语句)

5.跳出循环语句(breakable块) ​

scala
import scala.util.control.Breaks._  //相当于Java导入包时的*
breakable{ //使用break块
  for(i <- 1 to 10){
    if(i == 7){
      break()  //breakable将整个for循环包含,相当于break
    }
  }
}
scala
import scala.util.control.Breaks._  //相当于Java导入包时的*
//使用break块
for(i <- 1 to 10){
  breakable{
    if(i == 7){
      break()  //breakable将for循环的循环体包含,相当于continue
    }
  }
}

三、块表达式 ​

Scala中使用{}表示一个块表达式,快表达式有返回值,返回值为最后一个表达式的值

scala
val a = {
  println("1+1")
  1 + 1
}
println("a:" + a)  //结果为2

第三部分 方法与函数 ​

一、方法 ​

1.方法的定义 ​

scala
def 方法名称[(参数名:参数类型, ...):返回值类型] = {  //返回值类型可以省略(递归方法除外)
  方法体
  return value
}
def 方法名称[(参数名:参数类型, ...):返回值类型] = 方法返回值  //基本格式(简写)

def add=System.getProperty("user.name")  //无参方法
def add()=System.getProperty("user.name")  //空参方法,可作为最终表达式出现,实际是方法调用

def getMax(a:Int, b:Int):Int = { //得到两个数的最大值
  return if(a>=b) a else b
}
def getMax(a:Int, b:Int) = if(a>=b) a else b  //得到两个数的最大值(简写)

2.惰性方法 ​

当记录方法返回值的变量被声明为lazy时,方法的执行将被推迟到首次使用该值时,方法才会执行

示例:lazy val sum = getSum(1, 2) //当变量sum被使用时才执行方法

使用场景:

  1. 打开数据库连接
  2. 提升某些特定模块的启动时间
  3. 确保对象中的某些字段能优先初始化

3.方法参数 ​

  1. 默认参数:def 方法名称[(参数名:参数类型 = 默认值, ...):返回值类型] = {}
  2. 变长参数:def 方法名称[(参数名:参数类型*):返回值类型] = {}

4.方法调用 ​

  1. 后缀调用法:对象名.方法名(参数)
  2. 中缀调用法:对象名 方法名 参数(在Scala中,所有操作符都是方法)
  3. 花括号调用法:对象名.方法名{参数}
  4. 无括号调用法:方法名(方法没有参数时可以省略方法名后的括号)

二、函数 ​

可以看做是带有参数的表达式,其本质是一个完整的对象(变量),无需指定返回值类型

1.函数的定义 ​

scala
val 函数变量名 = (参数名:参数类型, ...) => {
  函数体
}

var mul = (x: Int, y: Int) => x*y  //多个参数的函数
val getTheAnswer = () => 42  //空参函数

2.方法与函数的区别 ​

  1. 方法是隶属于类或者对象的,在运行时,它是加载到JVM的方法区中
  2. 可以将函数对象赋值给一个变量, 在运行时,它是加载到JVM的堆内存中
  3. 函数是一个对象,继承自FunctionN, 函数对象有apply, curried, toString, tupled这些方法;方法则没有

3.方法转换为函数 ​

有事需要将方法转换为函数,可以使用"_"将方法转换为函数

基本格式:val 变量名 = 方法名 _

4.使用情形 ​

方法:需要执行一些与对象状态相关的操作(例如修改对象属性、访问对象私有成员等)

函数:需要进行一些纯粹的计算操作(例如数学运算、字符串处理等)

第四部分 面向对象编程 ​

一、实体类(class) ​

1.定义实体类 ​

scala
class Obj  //当类为空,没有任何成员,可以省略{}
class Obj(主构造器){  //构造器详见后面特殊方法部分
  //构造器代码块
}

2.创建对象 ​

scala
val obj = new Obj(...)  //创建一个Obj类型对象
val obj = new Obj  //当构造器的参数为空,可以省略()

3.成员变量初始化 ​

  1. 普通写法:val name:String = ""
  2. 类型推断:val name = ""
  3. 使用下划线初始化成员变量:var name:String = _ //初始化为默认值,val类型变量不可用

4.访问修饰符 ​

在Scala中,没有public修饰符,没有被标为private/protected的成员都是公共的

5.继承 ​

scala
class/object 子类([override val 变量名,] ...) extends 父类(...) {
  //成员方法
  override val 变量名  //可以通过override重写父类中val修饰的成员变量(var可以直接修改故不可override)
  override def 方法名 = {}  //重写非抽象方法必须使用override修饰符
}

二、单例对象(object) ​

单例对象表示全局仅有一个对象,也叫孤立对象,类似于Java中的静态对象

1.定义单例对象 ​

scala
object 单例对象名{ }  //定义一个单例对象

2.成员方法 ​

单例对象中定义的方法类似于Java中的静态方法

三、伴生对象 ​

1.伴生对象的作用 ​

在Scala中,通过伴生对象来实现类中又有实例成员又有静态成员的类似效果

一个class和object具有同样的名字,则称这个object为伴生对象,class为伴生类

注意要点:

  1. 伴生对象必须要和伴生类名字一样
  2. 伴生对象和伴生类应当处于同一个Scala源文件中
  3. 伴生对象和伴生类和可以相互访问private属性

2.定义 ​

scala
class Obj{  //伴生类
	//...
}

object Obj{  //伴生对象
	//...
}

四、类中特殊方法 ​

1.main方法 ​

由于在Scala中没有静态方法的概念,所以在Scala中,main方法必须放在一个单例对象中

scala
def main(args: Array[String]): Unit = {
  //主方法体
}

2.构造器 ​

scala
/** 主构造器参数列表直接定义在类名后,添加var/val表示直接通过主构造器定义成员变量 */
class 类名(var/val 参数名:类型 = 默认值, ...){  //构造器参数可以指定默认值
  //构造代码块(class中除了字段定义和方法定义的代码都是构造代码)
}
scala
class 类名(var/val 参数名:类型 = 默认值) {
  def this(var/val 参数名:类型 = 默认值) {
    this(...)  //辅助构造器第一行代码必须调用主构造器或者其他构造器
    //构造器代码
  }
}

3.apply方法 ​

在Scala中,可以通过伴生对象实现apply方法来实现在创建对象时免new的操作

scala
object 伴生对象名 {
  def apply(参数名:参数类型, ...) = new 类名(...)
}
val 对象名 = 伴生对象名(参数1, 参数2, ...)

4.getClass方法与classOf方法 ​

可以用于判定对象是否为指定类型对象(而非指定类型对象或其子类)

示例:p.getClass == classOf([MyClass]) //判断p是否为MyClass类型对象

五、其他类 ​

1.抽象类 ​

scala
abstract class 抽象类名 {
  //抽象字段:没有初始化值的变量
	val/var 抽象字段名:类型
  //抽象方法:没有方法体的方法
  def 方法名(参数:数据类型, ...):返回类型
}

2.匿名内部类 ​

作用:当对象方法只调用一次的时候使用;或作为方法的参数进行传递时使用

scala
new 类名(构造器参数列表) {  //若构造器参数列表为空,()可以省略不写
  //重写类中所有抽象内容
}

第五部分 数组与集合类 ​

一、数组 ​

1.创建定长数组(Array) ​

scala
//使用new关键字创建Array
var arr=new Array[数据类型](数组长度)
//直接使用Array创建并初始化一个数组
var arr=Array(value1, value2, ...)
scala
//访问定长数组
arr(1)  //访问数组中第一个元素
//操作定长数组
arr.toBuffer  //将数组转换成数组缓冲

2.创建变长数组(ArrayBuffer) ​

scala
//创建变长数组
val arr =  ArrayBuffer[数据类型]()
scala
//访问变长数组
arr(1)  //访问数组中第一个元素
//操作变长数组
arr += 1  //向变长数组arr中添加元素1
arr += (1,2,3,4)  //向变长数组arr中添加多个元素1,2,3,4
arr ++= Array(5,6,7)  //向变长数组arr中添加任何集合
arr.append(1)  //追加元素
arr.insert(2,20)  //在下标2前插入元素
arr.trimEnd(2)  //移除最后2个元素
arr.trimStart(1)  //移除最开始的一个元素

3.定长数组与变长数组的转换 ​

定长数组转为变长数组:arr.toBuffer

变长数组转为定长数组:arr.toArray

二、元组(Tuple) ​

固定元素的组合,可以装着多个不同类型的值,是不同类型的值的聚集

1.特点 ​

  1. 最多支持22个元素组合,分别对应类型Tuple1~Tuple22,相应也称为一元组、二元组、三元组、...
  2. 元组可以容纳不同类型的元素
  3. 元组不可变

2.创建元组 ​

scala
val t = (value1, ...)  //定义一个元组
val t = new Tuple<n>(...)  //使用new标识符创建元组
//例
val tuple3 = new Tuple3(1, 3.14, "Fred")

2.访问元组元素 ​

scala
val t1 = t._1  //取元组第1个元素(注意:使用此种方式取元素,下标从1开始)
val t2 = t.productElement(0)  //取元组第1个元素(下标从0开始)

3.遍历元组 ​

元组本身不是集合成员,所以元组不能作为for生成器的表达式,可以通过迭代器实现

scala
//方式1:迭代器遍历
for (elem <- t.productIterator) {
  print(elem)
}
//方式2:foreach遍历
t.productIterator.foreach(i => println(i)) //foreach是高阶函数
t.productIterator.foreach(print(_))

三、映射(Map) ​

1.创建映射 ​

scala
//一般方式构建
val m = Map("key1"->value1,"key2"->value2,"key3"->value3)
//使用元组构建
val m = Map(("key1", value1), ("key2", value2), ("key3", value3))
//构建可变Map
val m = scala.collection.mutable.Map(("key1", value1), ("key2", value2), ("key3", value3))

2.访问映射的值 ​

scala
//方式1
val v = m("key")  //key不存在,则抛出异常[java.util.NoSuchElementException]
val v = if(m.contains("key")) m("key") else 0
//方式2
val v = m.get("key")  //存在则返回Option对象Some,不存在返回None
val v = m.get("key").get   //Some再调用get取出值
//方式3:使用getOrElse()取值
val v = m.getOrElse("key",0)  //key不存在返回默认值

3.修改可变映射的信息 ​

scala
//修改value值(key存在)|添加键值对(key不存在)
m("newKey") = newValue
//添加键值对
m += ("newKey", newValue)
m += ("newKey"->newValue)
m += ("newKey1"->newValue1, "newKey2"->newValue2)
m ++= Map("newKey1"->newValue1, "newKey2"->newValue2)
//移除键值对
m - "oldKey"
m - ("oldKey1", "oldKey2")
m -- List("oldKey1", "oldKey2")

4.遍历映射 ​

scala
val res = m.keySet  //得到Map中所有键值对的迭代器(set集合)
val keys = m.keys  //得到Map中所有key的迭代器
val values = m.values  //得到Map中所有value的迭代器
//直接使用(k,v)表示二元组中的键和值
for ((k,v) <- m)
   println(k+":"+v)

四、列表(List) ​

1.创建列表与访问列表元素 ​

scala
val l = List(value1, value2, ...)
//访问列表中元素
l(idx)

2.相关操作 ​

scala
//添加元素到集合开头生成新集合
val l1 = value :: l
val l1 = value +: l
//添加元素到集合结尾生成新集合
val l2 = l :: value
val l2 = l :+ value
//添加一个集合生成新集合
val l3 = l1 ++: l2  //l1在前
val l3 = l1 ::: l2  //l2在前

3.遍历列表 ​

scala
//foreach遍历
l.foreach{x => print(x+" ")}
//map函数生成新列表
var nl = l.map{ x => x+1 }

4.可变列表(ListBuffer) ​

scala
val l = scala.collection.mutable.ListBuffer[数据类型](value1, value2, ...)

五、集合(Set) ​

1.创建可变集合 ​

scala
//创建不可变集合
val s = Set(value1, value2, ...)
//创建有序集合
val ts = scala.collection.immutable.TreeSet(alue1, value2, ...)

2.创建不可变集合 ​

scala
val s = new scala.collection.mutable.Hashset[数据类型]()

第六部分 Java调用Scala ​

一、流程与步骤 ​

1.获取Scala单例对象(object修饰) ​

使用Java中的类名$语法获取Scala对象,示例如下:

scala
import com.example.MyScalaObject$;  //导入Scala类
MyScalaObject$ myScalaObject = MyScalaObject$.MODULE$;  //获取Scala对象
Object result = myScalaObject.myMethod(...);

2.获取Scala示例对象(class修饰) ​

class类在Scala中是可以被实例化的,因此在Java中也使用正常的实例化方法来创建这个类的对象

scala
import com.example.MyScalaClass;  //导入Scala类
MyScalaClass myScalaClass = new MyScalaClass(...);  //生成类对象
Object result = myScalaClass.myMethod(...);  //调用实例对象方法