一、概述
在 Scala 中,字面量(Literals) 是直接表示固定值的表达式。Scala 支持各种类型的字面量,涵盖了数值、字符、字符串、布尔值等。
字面量类型一览
| 类型 | 示例 |
|---|---|
| 整型字面量 | 42, 0x2A, 255L |
| 浮点型字面量 | 3.14, 3.14f, 1.0e-10 |
| 布尔型字面量 | true, false |
| 字符字面量 | 'A', '\n', '\u0041' |
| 字符串字面量 | "Hello", """多行字符串""" |
| 符号字面量 | 'symbol |
| Null 值 | null |
| Unit 值 | () |
二、整型字面量
整型字面量用于表示整数类型的值。
类型后缀
- 默认为
Int类型 - 添加
L或l后缀表示Long类型
进制表示
| 进制 | 格式 | 示例 |
|---|---|---|
| 十进制 | 直接书写 | 42, 0, -99 |
| 十六进制 | 0x 或 0X 开头 |
0x2A, 0x0, 0XFF |
| 八进制 | Scala 2.10 之前支持,已移除 | - |
示例
scala
val decimal = 42 // Int 类型
val negative = -99 // Int 类型
val longValue = 255L // Long 类型
val hexValue = 0x2A // 十六进制,值为 42
val hexUpper = 0XFF // 十六进制,值为 255
类型范围
scala
val intMax: Int = 2147483647 // Int 最大值
val longMax: Long = 9223372036854775807L // Long 最大值
三、浮点型字面量
浮点型字面量用于表示浮点数类型的值。
类型后缀
- 默认为
Double类型 - 添加
f或F后缀表示Float类型 - 添加
d或D后缀显式表示Double类型
科学计数法
支持使用 e 或 E 表示指数。
示例
scala
// Double 类型(默认)
val double1 = 3.14
val double2 = -0.001
val double3 = 1.0e-10 // 科学计数法
val double4 = 1.0d // 显式 Double
// Float 类型
val float1 = 3.14f
val float2 = -0.001F
val float3 = 1.0e-10f // 科学计数法
精度对比
scala
val doubleValue = 3.141592653589793 // Double 精度
val floatValue = 3.141592653589793f // Float 精度(会丢失部分精度)
println(doubleValue) // 3.141592653589793
println(floatValue) // 3.1415927
四、布尔型字面量
布尔型字面量只有两个值:true 和 false。
scala
val isScalaFun = true
val isSkyGreen = false
// 条件表达式
val result = if (isScalaFun) "学习 Scala" else "放弃"
五、字符字面量
字符字面量使用单引号 ' 来定义,表示单个 Unicode 字符。
普通字符
scala
val charA = 'A'
val charB = 'B'
val digit = '7'
转义字符
| 转义序列 | 描述 |
|---|---|
\n |
换行符 |
\t |
制表符 |
\r |
回车符 |
\\ |
反斜杠 |
\' |
单引号 |
\" |
双引号 |
\b |
退格符 |
\f |
换页符 |
Unicode 字符
使用 \u 后跟 4 位十六进制数表示 Unicode 字符:
scala
val charUnicode = '\u0041' // 'A'
val charChinese = '\u4e2d' // '中'
示例
scala
val charA = 'A'
val newLine = '\n'
val tab = '\t'
val backslash = '\\'
val singleQuote = '\''
val unicode = '\u0041' // 'A'
println(s"字符: $charA")
println(s"Unicode: $unicode")
六、字符串字面量
字符串字面量使用双引号 " 来定义。
普通字符串
scala
val greeting = "Hello, World!"
val url = "菜鸟教程官网:www.runoob.com"
转义字符
字符串中可以使用转义字符:
scala
val multiLine = "Hello,\nWorld!" // 包含换行符
val quoted = "He said \"Hello\"" // 包含双引号
多行字符串
使用三重双引号 """ 定义多行字符串:
scala
val foo = """菜鸟教程
www.runoob.com
www.runnoob.com
以上三个地址都能访问"""
println(foo)
输出:
菜鸟教程
www.runoob.com
www.runnoob.com
以上三个地址都能访问
stripMargin 方法
使用 stripMargin 方法可以去除前导空白,默认以 | 作为分隔符:
scala
val quote = """The essence of Scala:
|Fusion of functional and object-oriented
|programming in a typed setting.""".stripMargin
println(quote)
输出:
The essence of Scala:
Fusion of functional and object-oriented
programming in a typed setting.
自定义分隔符
scala
val text = """Hello
#World
#Scala""".stripMargin('#')
println(text)
七、字符串插值
Scala 提供了强大的字符串插值功能,允许在字符串中嵌入变量和表达式。
s 插值器
s 插值器用于基本的字符串插值:
scala
val name = "John"
val mi = 'C'
val lastName = "Doe"
println(s"Name: $firstName $mi $lastName") // Name: John C Doe
// 表达式插值
println(s"2 + 2 = ${2 + 2}") // 2 + 2 = 4
val x = -1
println(s"x.abs = ${x.abs}") // x.abs = 1
f 插值器
f 插值器用于格式化字符串,支持 printf 风格的格式说明符:
scala
val name = "Joe"
val age = 42
val weight = 180.5
val pi = 3.14159
println(f"$name is $age years old, and weighs $weight%.1f pounds.")
// Joe is 42 years old, and weighs 180.5 pounds.
println(f"Pi is approximately $pi%.2f")
// Pi is approximately 3.14
raw 插值器
raw 插值器不处理转义字符,原样输出:
scala
// s 插值器处理转义字符
println(s"a\nb")
// 输出:
// a
// b
// raw 插值器不处理转义字符
println(raw"a\nb")
// 输出:a\nb
raw 插值器支持变量替换
scala
val foo = 42
println(raw"a\n$foo")
// 输出:a\n42
插值器对比
| 插值器 | 功能 | 示例 |
|---|---|---|
s |
基本插值,处理转义字符 | s"Hello $name" |
f |
格式化插值 | f"$pi%.2f" |
raw |
原样输出,不处理转义 | raw"a\nb" |
八、符号字面量
符号字面量被写成 '<标识符>,映射为 scala.Symbol 类的实例。
语法
scala
val symbol = 'x
等价于:
scala
val symbol = scala.Symbol("x")
Symbol 类定义
scala
package scala
final case class Symbol private (name: String) {
override def toString: String = "'" + name
}
使用场景
符号字面量常用于需要快速比较的标识符:
scala
val sym1 = 'hello
val sym2 = 'hello
println(sym1 == sym2) // true,相同名称的符号相等
println(sym1.name) // "hello"
注意事项
- 标识符不能以数字开头
- 符号是不可变的
- 相同名称的符号会指向同一个实例
九、Null 值
Null 是一个特殊的字面量,表示所有引用类型的空值。
特点
Null是scala.Null类型Null是每个引用类(继承自AnyRef的类)的子类Null不兼容值类型(如Int、Double等)
示例
scala
val nullValue: String = null
val nullRef: AnyRef = null
// 错误:Null 不兼容值类型
// val nullInt: Int = null // 编译错误
与 Java 的区别
在 Java 中,null 可以赋值给任何引用类型;在 Scala 中,null 只能赋值给 AnyRef 的子类型。
十、Unit 值
Unit 类型只有一个实例值,用字面量 () 表示,类似于 Java 中的 void。
特点
- 表示无返回值
- 只有一个实例
() - 常用于不需要返回值的方法
示例
scala
val unitValue: Unit = ()
def printHello(): Unit = {
println("Hello, Scala!")
}
// Unit 类型的变量
val result = printHello() // result 的类型是 Unit,值为 ()
与 void 的区别
| 特性 | Scala Unit | Java void |
|---|---|---|
| 是否有值 | 有,值为 () |
无 |
| 是否可以作为类型参数 | 可以 | 不可以 |
| 是否可以存储在容器中 | 可以 | 不可以 |
scala
// Unit 可以存储在容器中
val units: List[Unit] = List((), (), ())
// Unit 可以作为类型参数
def process[T](value: T): T = value
val result = process(()) // result: Unit = ()
十一、字面量类型总结
| 字面量类型 | 语法 | 结果类型 | 示例 |
|---|---|---|---|
| 整型(十进制) | 数字 | Int | 42 |
| 整型(十六进制) | 0x + 数字 |
Int | 0x2A |
| 长整型 | 数字 + L/l |
Long | 255L |
| 浮点型 | 数字 + 小数点 | Double | 3.14 |
| 单精度浮点 | 数字 + f/F |
Float | 3.14f |
| 布尔型 | true / false |
Boolean | true |
| 字符型 | '字符' |
Char | 'A' |
| 字符串 | "文本" |
String | "Hello" |
| 多行字符串 | """文本""" |
String | """多行""" |
| 符号 | '标识符 |
Symbol | 'x |
| Null | null |
Null | null |
| Unit | () |
Unit | () |
十二、完整示例代码
scala
object LiteralsExample {
def main(args: Array[String]): Unit = {
println("=== Scala 字面量示例 ===\n")
// 整型字面量
println("--- 整型字面量 ---")
val decimal = 42
val hex = 0x2A
val longValue = 255L
println(s"十进制: $decimal")
println(s"十六进制: $hex")
println(s"长整型: $longValue")
// 浮点型字面量
println("\n--- 浮点型字面量 ---")
val doubleValue = 3.141592653589793
val floatValue = 3.14f
val scientific = 1.0e-10
println(s"Double: $doubleValue")
println(s"Float: $floatValue")
println(s"科学计数法: $scientific")
// 字符字面量
println("\n--- 字符字面量 ---")
val charA = 'A'
val charNewLine = '\n'
val charTab = '\t'
val unicode = '\u0041'
println(s"字符: $charA")
println(s"Unicode (\\u0041): $unicode")
println(s"换行符: ${charNewLine.toInt}")
println(s"制表符: ${charTab.toInt}")
// 字符串字面量
println("\n--- 字符串字面量 ---")
val greeting = "Hello, World!"
val multilineString = """This is
|a multi-line
|string.""".stripMargin
println(s"普通字符串: $greeting")
println(s"多行字符串:\n$multilineString")
// 字符串插值
println("\n--- 字符串插值 ---")
val name = "Scala"
val version = 3
println(s"欢迎学习 $name!")
println(s"$name 版本: $version")
println(f"Pi: ${math.Pi}%.4f")
println(raw"原始字符串: a\nb")
// 布尔字面量
println("\n--- 布尔字面量 ---")
val isScalaFun = true
val isSkyGreen = false
println(s"Scala 有趣吗: $isScalaFun")
println(s"天空是绿色的吗: $isSkyGreen")
// 符号字面量
println("\n--- 符号字面量 ---")
val symbol = 'hello
println(s"符号: $symbol")
println(s"符号名称: ${symbol.name}")
// 特殊字面量
println("\n--- 特殊字面量 ---")
val nullValue: String = null
val unitValue: Unit = ()
println(s"Null 值: $nullValue")
println(s"Unit 值: $unitValue")
// raw 插值器示例
println("\n--- raw 插值器示例 ---")
val path = raw"C:\new\test"
println(s"文件路径: $path")
// f 插值器格式化示例
println("\n--- f 插值器格式化示例 ---")
val price = 99.99
val quantity = 10
println(f"单价: $$$price%.2f")
println(f"总价: ${price * quantity}%.2f")
}
}
十三、最佳实践
1. 使用字符串插值代替字符串拼接
scala
// 不推荐
val message = "Hello, " + name + "!"
// 推荐
val message = s"Hello, $name!"
2. 使用多行字符串处理复杂文本
scala
// 不推荐
val sql = "SELECT * FROM users\nWHERE age > 18\nORDER BY name"
// 推荐
val sql = """SELECT * FROM users
|WHERE age > 18
|ORDER BY name""".stripMargin
3. 使用 raw 插值器处理文件路径
scala
// 不推荐
val path = "C:\\new\\test"
// 推荐
val path = raw"C:\new\test"
4. 使用 f 插值器进行格式化输出
scala
// 不推荐
val formatted = String.format("%.2f", price)
// 推荐
val formatted = f"$price%.2f"
5. 避免使用 null,使用 Option
scala
// 不推荐
def findUser(id: Int): User = null
// 推荐
def findUser(id: Int): Option[User] = None
十四、常见问题
Q1: 为什么十六进制 0x2A 输出是 42?
十六进制 0x2A 转换为十进制就是 42。打印时会显示十进制值。
Q2: Float 和 Double 的精度差异?
Float:32位,约 6-7 位有效数字Double:64位,约 15-16 位有效数字
Q3: 什么时候使用符号字面量?
符号字面量适用于需要快速比较的标识符场景,如 Map 的键、动态方法名等。
Q4: Unit 和 null 的区别?
Unit:表示无值,用于不需要返回值的场景null:表示空引用,用于引用类型的空值