Scala 字面量

一、概述

在 Scala 中,字面量(Literals) 是直接表示固定值的表达式。Scala 支持各种类型的字面量,涵盖了数值、字符、字符串、布尔值等。

字面量类型一览

类型 示例
整型字面量 42, 0x2A, 255L
浮点型字面量 3.14, 3.14f, 1.0e-10
布尔型字面量 true, false
字符字面量 'A', '\n', '\u0041'
字符串字面量 "Hello", """多行字符串"""
符号字面量 'symbol
Null 值 null
Unit 值 ()

二、整型字面量

整型字面量用于表示整数类型的值。

类型后缀

  • 默认为 Int 类型
  • 添加 Ll 后缀表示 Long 类型

进制表示

进制 格式 示例
十进制 直接书写 42, 0, -99
十六进制 0x0X 开头 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 类型
  • 添加 fF 后缀表示 Float 类型
  • 添加 dD 后缀显式表示 Double 类型

科学计数法

支持使用 eE 表示指数。

示例

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

四、布尔型字面量

布尔型字面量只有两个值:truefalse

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 是一个特殊的字面量,表示所有引用类型的空值。

特点

  • Nullscala.Null 类型
  • Null 是每个引用类(继承自 AnyRef 的类)的子类
  • Null 不兼容值类型(如 IntDouble 等)

示例

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:表示空引用,用于引用类型的空值

相关推荐
Amumu121382 小时前
JS:ES6~ES11基础语法(二)
开发语言·前端·javascript
Amumu121382 小时前
Js:ES6~ES11基础语法(一)
开发语言·前端·javascript
m0_569881472 小时前
跨语言调用C++接口
开发语言·c++·算法
zdl6862 小时前
搭建Golang gRPC环境:protoc、protoc-gen-go 和 protoc-gen-go-grpc 工具安装教程
开发语言·后端·golang
Memory_荒年2 小时前
Gateway:微服务前台的“瑞士军刀”小姐姐
后端
希望永不加班2 小时前
SpringBoot 内置服务器(Tomcat/Jetty/Undertow)切换
服务器·spring boot·后端·tomcat·jetty
Sammyyyyy2 小时前
9个Python库把一个月的AI开发周期缩短到了3天
人工智能·后端·python·servbay
LilySesy2 小时前
【与AI+】英语day1——ABAP基础与数据类型
开发语言·ai·sap·abap
你不是我我2 小时前
【Java 开发日记】我们来说一下 b+ 树与 b 树的区别
java·开发语言