Scala 变量怎么声明:先分清 `val` 和 `var`
在 Scala 里,初学者最先遇到的不是复杂类型系统,而是变量该怎么定义。这里首先要分清两种变量声明方式:val 用于不可变变量,var 用于可变变量。
val 的作用类似 Java 里的 final:变量一旦绑定,就不能重新赋值;而 var 允许后续修改。
// immutable
val s = "hello"
s = "hello, world" // compile error: reassignment to val
val dog = new Dog("Tom")
// mutable
var i = 123
i = 456 // compile pass
实际开发里,val 往往是更常见的选择,因为不可变数据更容易推导,也更不容易引入副作用。只有在确实需要修改值时,再考虑使用 var。
Scala 需要显式写类型吗:多数时候不用
Scala 编译器可以根据 = 右侧的值自动推断变量类型,所以很多场景下不必手动标注类型。这也是 Scala 代码通常比传统强类型语言更紧凑的原因之一。

val s: String = "hello"
var i: Int = 123
上面这种写法当然是允许的,但如果类型一眼就能看出来,显式声明通常会显得冗余。多数情况下,直接交给编译器推断即可。
什么情况下建议把类型写出来
虽然“让编译器推断”是默认推荐,但显式标注类型并不是没有意义。尤其在调用第三方库时,如果方法返回值不直观,或者 API 命名不能清楚说明结果类型,手动写出类型通常能明显提升可读性。
相比事后再用注释解释,直接把类型写在变量声明里,往往更符合“见名知意”的代码风格。
Scala 有哪些内置数据类型
Scala 内置了不少基础数据类型,而且这些类型都被封装为成熟的 object,并不是传统意义上的原始类型(如 int、float)。

整数类型:默认是 `Int`
下面这些都属于整数类型:
val b: Byte = 1
val i: Int = 1
val l: Long = 1
val s: Short = 1
其中,整数字面量默认会被推断为 Int。如果你希望变量是 Byte、Long 或 Short,就需要通过 : {数据类型} 的方式显式声明。
小数类型:默认是 `Double`
小数字面量的默认类型是 Double。如果希望使用 Float,同样需要显式标注:
val d = 2.0 // default "Double" type
val f: Float = 3.0 // set to `Float` type
另外三类常用基本类型
除了整数和浮点数,Scala 也内置了 Boolean、String、Char:
val b = true // default "Boolean" type
val s = "hello" // default "String" type
val c = 'a' // default "Char" type
9 种基本数据类型的值范围
原文同时给出了 Scala 官方对 9 种基本数据类型取值范围的说明,保留如下:
| Data Type | Possible Values |
|---|---|
| Boolean | true or false |
| Byte | 8-bit signed two’s complement integer (-2^7 to 2^7-1, inclusive) |
| Short | 16-bit signed two’s complement integer (-2^15 to 2^15-1, inclusive) |
| Int | 32-bit two’s complement integer (-2^31 to 2^31-1, inclusive) |
| Long | 64-bit two’s complement integer (-2^63 to 2^63-1, inclusive) |
| Float | 32-bit IEEE 754 single-precision float (1.40129846432481707e-45 to 3.40282346638528860e+38) |
| Double | 64-bit IEEE 754 double-precision float (4.94065645841246544e-324d to 1.79769313486231570e+308d) |
| Char | 16-bit unsigned Unicode character (0 to 2^16-1, inclusive) |
| String | a sequence of Char |
Scala 字符串怎么处理
字符串是 Scala 中最常见的日常操作之一。原文重点介绍了几种字符串拼接、插值和多行文本处理方式,这部分很适合放在一起理解。

先定义两个字符串变量:
val firstName = "Shuai"
val lastName = "Li"
方法一:用 `+` 直接拼接
val name = firstName + " " + lastName // Shuai Li
这种方式最直接,适合非常简单的拼接场景。
方法二:用 `s` 字符串插值
val name = s"$firstName $lastName" // Shuai Li
s 插值比 + 更清晰,特别是在变量较多时更容易读。
变量也可以写成带花括号的形式:
val name = s"${firstName} ${lastName}" // Shuai Li
更重要的是,花括号里不只是变量,还可以直接写表达式:
val calculation_description = s"1 + 1 = ${1 + 1}" // 1 + 1 = 2
插值时的转义问题
使用 s 插值时,遇到特殊字符需要注意转义。例如金额里的 $:
println(s"The book is $$30.54") // The book is $30.54
双引号也是常见问题。下面给出一个错误示例和一个可工作的示例:
println(s"The focus of this book is on "clean code".") // compile error
println("""The focus of this book is on "clean code".""") // The focus of this book is on "clean code".
也就是说,包含双引号的复杂字符串内容,可以借助 三重双引号 来处理。
方法三:用 `f` 做格式化插值
f 插值适合输出格式化字符串,风格接近其他语言里的 printf。使用时,变量后面需要追加格式说明符:
val money = 7.856
println(f"$name%s has $money%2.2f yuan left") // Shuai Li has 7.86 yuan left
如果你既想保留插值的可读性,又需要控制小数位、宽度等输出格式,f 会比手工拼接更合适。
多行字符串与 `stripMargin`
Scala 可以直接用三个双引号来定义多行字符串:
val introduction =
"""My name
is Shuai Li..."""
println(introduction)
输出结果如下:
My name
is Shuai Li...
问题也很明显:除了第一行,后续各行会保留缩进。为了解决这个问题,可以在每行前加上 |,并调用 stripMargin:
val introduction =
"""My name
|is Shuai Li...""".stripMargin
println(introduction)
输出会变成:
My name
is Shuai Li...
这也是 Scala 处理中长文本时很常见的一种写法。
大数场景怎么办:`BigInt` 和 `BigDecimal`
当内置整数或浮点类型无法满足精度和范围要求时,Scala 还提供了两种常见的大数类型:
BigInt:大整数BigDecimal:大十进制数(小数)
和 Java 中对应类相比,Scala 里的这两种类型支持你熟悉的数值操作符,写法更自然。下面是原文给出的 REPL[1] 示例。
`BigInt` 示例
scala> val bi = BigInt(100000001)
val bi: scala.math.BigInt = 100000001
scala> bi + bi
val res2: scala.math.BigInt = 200000002
scala> bi - bi
val res3: scala.math.BigInt = 0
scala> bi * bi
val res4: scala.math.BigInt = 10000000200000001
`BigDecimal` 示例
scala> val bd = BigDecimal(10000.123)
val bd: scala.math.BigDecimal = 10000.123
scala> bd + bd
val res0: scala.math.BigDecimal = 20000.246
scala> bd * bd
val res1: scala.math.BigDecimal = 100002460.01512
如果你的代码涉及超大整数计算、高精度金额、统计结果累积等场景,这两种类型通常比普通数值类型更稳妥。
参考资料
- [1] Scala REPL, docs.scala-lang.org/overviews/s…







