Swift 字面量
字面量(literal)是直接写在源码里、一眼就能看出类型的值,例如 42、3.14、"Runoob" 和 true。
Swift 会根据字面量的写法和上下文推断类型,所以写代码时通常不需要额外标注。
什么是字面量
下面三行赋值,右侧都是字面量,左侧变量的类型由 Swift 自动推断出来。
实例
let aString = "Runoob" // 推断为 String
let aBool = true // 推断为 Bool
print(aNumber, aString, aBool)
以上程序执行结果为:
3 Runoob true
如果上下文无法推断,或者你想要更精确的类型,可以显式写类型标注,例如 let price: Double = 9.9。
整型字面量
整型字面量可以用十进制、二进制、八进制或十六进制书写,前三种写法最终得到的都是同一个 Int 值。
| 进制 | 前缀 | 示例 | 十进制值 |
|---|---|---|---|
| 十进制 | 无 | 17 | 17 |
| 二进制 | 0b | 0b10001 | 17 |
| 八进制 | 0o | 0o21 | 17 |
| 十六进制 | 0x | 0x11 | 17 |
数字中间可以插入下划线 _ 方便阅读,下划线会被完全忽略,不影响数值。
实例
let binaryInteger = 0b10001 // 二进制
let octalInteger = 0o21 // 八进制
let hexadecimalInteger = 0x11 // 十六进制
print(decimalInteger, binaryInteger, octalInteger, hexadecimalInteger)
// 下划线只用于分隔,不参与计算
let oneMillion = 1_000_000
let cardNumber = 1234_5678_9012_3456
print(oneMillion, cardNumber)
以上程序执行结果为:
17 17 17 17 1000000 1234567890123456
注意:字面量本身没有固定的位宽,具体是 Int 还是 Int8 由上下文决定。上面的例子没有标注类型,Swift 统一推断为 Int。
浮点字面量
浮点字面量由整数部分、小数点、小数部分和指数部分组成,写法比整型多一些。
没有显式标注时,浮点字面量默认推断为 Double(64 位)。
| 写法 | 示例 | 值 | 说明 |
|---|---|---|---|
| 普通十进制 | 12.1875 | 12.1875 | 最常见 |
| 十进制指数 | 1.21875e1 | 12.1875 | 乘以 10 的 1 次方 |
| 十六进制 | 0xC.3p0 | 12.1875 | (12 + 3/16) × 2⁰ |
| 十六进制指数 | 0x1p2 | 4.0 | 1 × 2² |
| 下划线分隔 | 1_000_000.000_000_1 | 1000000.0000001 | 只为可读性 |
十六进制浮点数的指数部分用字母 p(而不是 e),表示乘以 2 的多少次方。
实例
let exponentDouble = 1.21875e1 // 1.21875 × 10¹
let hexDouble = 0x1p2 // 1 × 2² = 4.0
let hexDouble2 = 0xC.3p0 // (12 + 3/16) × 2⁰ = 12.1875
let readableDouble = 1_000_000.000_000_1
print(decimalDouble, exponentDouble, hexDouble, hexDouble2, readableDouble)
以上程序执行结果为:
12.1875 12.1875 4.0 12.1875 1000000.0000001
负数只需要在前面加一元减号,例如 -42.5,它等价于对字面量 42.5 取负。
字符串字面量
字符串字面量由一对双引号包起来,里面可以放普通字符、转义序列和插值表达式。
实例
let greeting = "你好,\(site)" // 反斜线加圆括号做字符串插值
print(greeting)
以上程序执行结果为:
你好,www.runoob.com
转义序列
Swift 支持的转义序列不多,只有下面这几个;写错了编译器会直接报错。
| 转义序列 | 含义 |
|---|---|
\0 | 空字符(null) |
\\ | 反斜线本身 |
\t | 水平制表符 |
\n | 换行 |
\r | 回车 |
\" | 双引号 |
\' | 单引号 |
\u{n} | Unicode 标量,n 为 1 到 8 位十六进制数 |
实例
print(stringL)
print("反斜线:\\ 单引号:\'")
let han = "\u{4E2D}"
print("han = \(han),count = \(han.count)")
以上程序执行结果为:
Hello World 菜鸟教程:"http://www.runoob.com" 反斜线:\ 单引号:' han = 中,count = 1
注意:Swift 没有 C 语言里的 \b、\f、\v,也不支持八进制转义。写 "\b" 会得到 error: invalid escape sequence in literal。
多行字符串
用一对三引号 """ 可以写跨行的字符串,闭合三引号的缩进决定了每行被剥掉多少缩进。
实例
Runoob
www.runoob.com
"""
print(text)
print("长度:\(text.count)")
// 多行字符串里可以直接写双引号,不需要转义
let quoted = """
他说:"欢迎来到 Runoob"
"""
print(quoted)
以上程序执行结果为:
Runoob www.runoob.com 长度:21 他说:"欢迎来到 Runoob"
原始字符串
在三引号或双引号外面再加一个 #,就得到原始字符串:反斜线不再触发转义,\n 只是两个普通字符。
原始字符串里要做插值,需要在反斜线后再加一个 #,写成 \#(...)。
实例
let rawPath = #"目录 "C:\Users\Runoob" 里的 \n 不换行"#
print(rawPath)
// 原始字符串里插值要写成 \#(...)
let number = 17
let rawInterp = #"插值仍然可用:\#(number)"#
print(rawInterp)
以上程序执行结果为:
目录 "C:\Users\Runoob" 里的 \n 不换行 插值仍然可用:17
布尔字面量
布尔字面量只有两个:true 和 false,它们的类型是 Bool。
实例
let isClosed = false
print(isRunoob, isClosed)
print("isRunoob 的类型是 \(type(of: isRunoob))")
以上程序执行结果为:
true false isRunoob 的类型是 Bool
注意:nil 不是布尔字面量,它表示「没有值」,只能赋给可选类型。Swift 也没有「0、空字符串为假」这类隐式转换,条件位置必须放一个真正的 Bool,详见第 9 篇《Swift 条件语句》。
数组与字典字面量
数组字面量用方括号列出元素,字典字面量用「键: 值」的形式列出键值对。
实例
print(sites)
print("元素个数:\(sites.count)")
let info = ["name": "Runoob", "site": "www.runoob.com"]
print(info["name"]!, info["site"]!, info.count)
以上程序执行结果为:
["Runoob", "RUNOOB", "菜鸟教程"] 元素个数:3 Runoob www.runoob.com 2
注意:字典是无序的,遍历同一个字典两次,打印出的键值对顺序可能不同,所以上面用具体的键取值,而不是直接打印整个字典。
常见问题
下面几个问题是初学者写字面量时最常遇到的。
| 问题 | 说明 |
|---|---|
浮点字面量为什么打印成 4.0 | 它的类型是 Double,打印时会带上小数点 |
0b102 能编译吗 | 不能,二进制只允许 0 和 1 |
| 字面量里的下划线会被算进数值吗 | 不会,下划线只起分隔作用 |
"\b" 为什么报错 | Swift 没有这个转义序列,用 \u{8} 表示退格字符 |
| 字典字面量能保证顺序吗 | 不能,字典本身无序 |
