2. 变量和数据类型
2.1 注释
基本语法
单行注释:
//
多行注释:
/* */
文档注释:
/**
*
*/
注意事项
Scala注释使用和Java完全一样
2.2 变量和常量
基本语法
var 变量名 [: 变量类型] = 初始值
val 常量名 [: 常量类型] = 初始值
能用常量的地方不用变量
注意事项
- 声明变量时,类型可以省略,编译器自动推导,即类型推导
- 类型确定后不可修改
- 变量声明时,必须要有初始值
在声明/定义变量时,可以使用var或者val来修饰,var修饰的变量可变,val修饰的变量不可变
var修饰的对象引用可以改变,val修饰的对象则不可改变,但对象的状态(字段)是可以改变的
- 类构造方法中的属性加上var/val才能被访问到,能否改变也取决于此
- 类属性也可以写在字段中,构造方法形如
def this(..) {}
1
2
3
4
5
6
7
8class Student(name: String, var age: Int) { }
var alice = new Student("alice", 20)
alice = new Student("Alice", 21)
alice = null
val bob = new Student("bob", 23)
bob.age = 24
2.3 标识符的命名规范
命名规则
Scala中的标识符声明,基本和Java一致,但是细节上会有所变化,有以下三点
- 以字母或者下划线开头,后接字母、数字、下划线
- 以操作符开头,且只包含操作符(+-*/#!等)
- 用反引号``包括的任意字符串,即使是Scala关键字也可以
2.4 字符串输出
基本语法
- 字符串间用 + 号连接,* 表示复制
- printf用法:通过 % 传值
- 字符串模板(插值字符串):通过 $ 获取变量值
案例实操
1 |
|
2.5 控制台输入
基本语法
StdIn.readLine()
StdIn.readInt()
StdIn.readDouble()
- …
案例实操
1 |
|
2.6 读写文件
基本语法
Source.fromFile("...")
new PrintWriter(new File("..."))
案例实操
1 |
|
2.7 数据类型
- Scala 中一切数据都是对象,都是 Any 的子类
- Scala 中数据类型分为两大类:数值类型(AnyVal),引用类型(AnyRef),不管是值类型还是引用类型都是对象
- Scala 数据类型仍然遵守,低精度的值类型向高精度的值类型,自动转换(隐式转换),图中虚线
- Scala 中的 StringOps 是对 Java 的 String 的增强
- Unit:对应 Java 中的 void,用于方法返回值的位置,表示方法没有返回值。Unit 是一个数据类型,只有一个对象就是()。Void 不是数据类型,只是一个关键词
- Null 是一个类型,只有一个对象就是 null。它是所有引用类型(AnyRef)的子类
- Nothing,是所有数据类型的子类,主要用在一个函数没有明确返回值时使用,因为这样我们可以把抛出的返回值,返回给任何的变量或者函数
- Long 需要在数字后加 L,同理,Float 类型需要加 F
2.8 Unit、Null、Nothing
基本说明
数据类型 | 描述 |
---|---|
Unit | 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。 |
Null | null, Null类型只有一个实例值null |
Nothing | Nothing类型在Scala的类层级最低端;它是任何其他类型的子类型。当一个函数,我们确定没有正常的返回值,可以用Nothing来指定返回类型,这样有一个好处,就是我们可以把返回的值(异常)赋给其它的函数或者变量(兼容性) |
案例实操
Unit 类型用来标识过程,也就是没有明确返回值的函数。
Unit 类似于 Java 里的 void。Unit只有一个实例————(),这个实例也没有实质意义
1
2
3
4
5
6def main(args: Array[String]): Unit = {
def sayOk : Unit = {}
println(sayOk)
}
//输出()Null 类只有一个实例对象,Null 类似于 Java 中的 null 引用。Null 可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
1
2
3
4
5var cat = new Cat()
cat = null // 正确
var n1: Int = null // 错误
println("n1: " + n1)Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于 Nothing 是其他任意类型的子类,他还能跟要求返回值的方法兼容。
1
2
3
4
5
6def main(args: Array[String]): Unit = {
def test(): Nothing = {
throw new Exception()
}
test()
}
2.9 类型转换
2.9.1 数值类型自动转换
基本说明
自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算
把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
Byte,Short和Char不会相互自动转化
Byte,Short和Char三者可以计算,计算时首先转换为Int类型
扩展
1
2
3
4
5
6
7def main(args: Array[String]): Unit = {
// 00000000 00000000 00000000 10000010
var n: Int = 130
// 10000010
var b: Byte = n.toByte
println(b) // -126
}
2.9.2 强制类型转换
基本说明
自动类型转换的逆过程,将精度大的数值类型转换为精度小的数值类型。使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意。
var num : Int = 2.7.toInt
注意事项
- 将数据由高精度转换为低精度,就需要使用到强制转换
- 强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
2.9.3 数值类型和String类型间转换
基本语法
- 基本类型转String类型: 将基本类型的值
+""
即可 - String类型转基本数值类型:
s.toInt, s.toFloat, s.toDouble
…
3. 运算符
大部分与Java相同,仅列举不同之处
3.1 关系(比较)运算符
- 在 Scala 中,== 是类中定义的方法,其底层调用时,调用的是此类的 equals 方法
String 的 equals 方法比较的是两个对象的具体的值。
eq 方法比较的是两个对象的地址,其底层调用的是 Java 中的 == 比较运算符。
1 |
|
3.2 赋值运算符
Scala 中没有 ++, — 操作符,可以通过 +=, -= 实现
3.3 三元运算符
Scala 中没有三元运算符 ?:,可以用if-else实现 val res = if (...) x else y
3.4 Scala运算符本质
Scala中其实是没有运算符的,所有的运算符都是方法,任何具有单个参数的方法都可以用作中缀运算符。
- 当调用对象的方法时,点.可以省略
- 如果函数参数只有一个,或者没有参数,()可以省略
1 |
|
4. 流程控制
4.1 if-else
大部分与Java相同
不同点
Scala中if-else表达式其实是有返回值的,具体返回值取决于满足条件的代码体的最后一行
1 |
|
4.2 switch
Scala中没有Switch,而是使用模式匹配处理
4.3 for
4.3.1 范围数据循环(to)
基本语法
1 |
|
- i 表示循环的变量,<- 表示为 i 赋值
- i 从 1-3 循环,前后闭合
4.3.2 范围数据循环(until)
基本语法
1 |
|
- i 从 1-2 循环,前闭后开
4.3.3 循环守卫
基本语法
1 |
|
- 循环守卫,即循环保护式(条件判断式、守卫)。保护式为true才会进入循环体内部
4.3.4 循环步长(by)
基本语法
1 |
|
4.3.5 嵌套循环
基本语法
1 |
|
4.3.6 引入变量
基本语法
1 |
|
for推导式一行中由多个表达式时,要加
;
隔断逻辑for推导式有一个约定,当仅包含单一表达式时使用圆括号,否则一行一个表达式,并用花括号替代
1
2
3
4
5
6for {
i <- 1 to 3
j = 4 - i
} {
println("i = " + i + " j = " + j)
}
4.3.7 循环返回值
基本语法
1 |
|
- 将遍历过程中处理的结果返回到一个新的Vector集合,使用yield关键字
- 开发中很少使用
案例实操
1 |
|
4.3.8 倒叙打印
基本语法
1 |
|
4.4 while、do..while
和Java相同
- 与for不同,while没有返回值,即while语句的结果是Unit类型()
4.5 循环中断
基本说明
Scala内置控制结构去掉了break和continue,是为了更好地适应函数式编程
,推荐使用函数式风格解决break和continue的问题。
Scala中使用breakable控制结构来实现break和continue功能
案例实操
异常方式退出循环
1
2
3
4
5
6
7
8try {
for (elem <- 1 to 10) {
println(elem)
if (elem == 5) throw new RuntimeException
}
} catch {
case e: RuntimeException => e.printStackTrace()
}采用Scala自带函数退出循环
1
2
3
4
5
6Breaks.breakable {
for (elem <- 1 to 10) {
println(elem)
if (elem == 5) Breaks.break()
}
}对break进行省略
1
2
3
4
5
6breakable {
for (elem <- 1 to 10) {
println(elem)
if (elem == 5) break
}
}