Scala 数据类型
Scala 拥有丰富而强大的类型系统,本章将详细介绍 Scala 的各种数据类型,包括基本类型、引用类型和类型层次结构。
类型层次结构
Scala 的类型系统有一个统一的层次结构:
Any
├── AnyVal (值类型)
│ ├── Double
│ ├── Float
│ ├── Long
│ ├── Int
│ ├── Short
│ ├── Byte
│ ├── Char
│ ├── Boolean
│ └── Unit
└── AnyRef (引用类型)
├── String
├── List
├── Option
└── 所有其他引用类型Any 类型
Any 是所有类型的超类型:
scala
val items: List[Any] = List(1, "hello", true, 3.14)
def printAny(x: Any): Unit = {
println(s"Value: $x, Type: ${x.getClass.getSimpleName}")
}
items.foreach(printAny)
// 输出:
// Value: 1, Type: Integer
// Value: hello, Type: String
// Value: true, Type: Boolean
// Value: 3.14, Type: Double基本数据类型(AnyVal)
数值类型
整数类型
scala
// Byte: 8位有符号整数 (-128 to 127)
val byteValue: Byte = 127
val byteMin: Byte = Byte.MinValue // -128
val byteMax: Byte = Byte.MaxValue // 127
// Short: 16位有符号整数 (-32,768 to 32,767)
val shortValue: Short = 32767
val shortMin: Short = Short.MinValue // -32768
val shortMax: Short = Short.MaxValue // 32767
// Int: 32位有符号整数 (-2^31 to 2^31-1)
val intValue: Int = 2147483647
val intMin: Int = Int.MinValue // -2147483648
val intMax: Int = Int.MaxValue // 2147483647
// Long: 64位有符号整数 (-2^63 to 2^63-1)
val longValue: Long = 9223372036854775807L
val longMin: Long = Long.MinValue
val longMax: Long = Long.MaxValue浮点类型
scala
// Float: 32位IEEE 754单精度浮点数
val floatValue: Float = 3.14159f
val floatMin: Float = Float.MinValue
val floatMax: Float = Float.MaxValue
val floatPositiveInfinity: Float = Float.PositiveInfinity
val floatNegativeInfinity: Float = Float.NegativeInfinity
val floatNaN: Float = Float.NaN
// Double: 64位IEEE 754双精度浮点数
val doubleValue: Double = 3.141592653589793
val doubleMin: Double = Double.MinValue
val doubleMax: Double = Double.MaxValue
val pi: Double = math.Pi
val e: Double = math.E数值类型转换
scala
val intVal = 42
val longVal: Long = intVal.toLong // 安全转换
val doubleVal: Double = intVal.toDouble // 安全转换
val floatVal: Float = intVal.toFloat // 安全转换
// 可能丢失精度的转换
val bigLong = 1234567890123L
val intFromLong: Int = bigLong.toInt // 可能溢出
// 检查转换是否安全
def safeToInt(long: Long): Option[Int] = {
if (long >= Int.MinValue && long <= Int.MaxValue) {
Some(long.toInt)
} else {
None
}
}字符类型
scala
// Char: 16位无符号Unicode字符
val char1: Char = 'A'
val char2: Char = '\u0041' // Unicode 表示的 'A'
val char3: Char = 65.toChar // ASCII 码转字符
// 字符操作
val isLetter: Boolean = char1.isLetter
val isDigit: Boolean = char1.isDigit
val isUpper: Boolean = char1.isUpper
val lower: Char = char1.toLower
val upper: Char = char1.toUpper
// 字符范围
val charMin: Char = Char.MinValue // '\u0000'
val charMax: Char = Char.MaxValue // '\uffff'布尔类型
scala
// Boolean: true 或 false
val isTrue: Boolean = true
val isFalse: Boolean = false
// 布尔运算
val and: Boolean = true && false // false
val or: Boolean = true || false // true
val not: Boolean = !true // false
// 条件表达式
val result: String = if (isTrue) "yes" else "no"
// 布尔值与其他类型的关系
val boolToInt: Int = if (isTrue) 1 else 0Unit 类型
scala
// Unit: 表示无有意义的值,类似于 Java 的 void
def printMessage(msg: String): Unit = {
println(msg)
}
val unitValue: Unit = () // Unit 的唯一值
val unitFromMethod: Unit = printMessage("Hello")
// Unit 在表达式中的使用
val result: Unit = {
val x = 10
val y = 20
println(s"Sum: ${x + y}") // 返回 Unit
}引用类型(AnyRef)
字符串类型
scala
// String: 不可变字符序列
val str1: String = "Hello, World!"
val str2: String = new String("Hello")
// 字符串操作
val length: Int = str1.length
val upper: String = str1.toUpperCase
val lower: String = str1.toLowerCase
val substring: String = str1.substring(0, 5) // "Hello"
// 字符串比较
val isEqual: Boolean = str1 == "Hello, World!" // true
val isEqualRef: Boolean = str1 eq str2 // false (引用比较)
// 字符串插值
val name = "Alice"
val age = 25
val interpolated = s"Name: $name, Age: $age"
val formatted = f"Pi: ${math.Pi}%.2f"
val raw = raw"Path: C:\Users\$name"集合类型概览
scala
// List: 不可变链表
val list: List[Int] = List(1, 2, 3, 4, 5)
val emptyList: List[String] = List.empty[String]
val nilList: List[Int] = Nil
// Array: 可变数组
val array: Array[Int] = Array(1, 2, 3, 4, 5)
val arrayOfStrings: Array[String] = Array("a", "b", "c")
// Vector: 不可变向量
val vector: Vector[Int] = Vector(1, 2, 3, 4, 5)
// Set: 不可变集合
val set: Set[Int] = Set(1, 2, 3, 2, 1) // Set(1, 2, 3)
// Map: 不可变映射
val map: Map[String, Int] = Map("a" -> 1, "b" -> 2, "c" -> 3)选项类型(Option)
scala
// Option: 表示可能存在或不存在的值
val someValue: Option[String] = Some("Hello")
val noneValue: Option[String] = None
// Option 的使用
def findUser(id: Int): Option[String] = {
if (id > 0) Some(s"User$id") else None
}
val user1 = findUser(1) // Some("User1")
val user2 = findUser(-1) // None
// Option 的操作
val result1 = someValue.getOrElse("Default") // "Hello"
val result2 = noneValue.getOrElse("Default") // "Default"
val mapped = someValue.map(_.toUpperCase) // Some("HELLO")
val filtered = someValue.filter(_.length > 3) // Some("Hello")
// 模式匹配
val message = someValue match {
case Some(value) => s"Found: $value"
case None => "Not found"
}元组类型(Tuple)
scala
// 元组: 固定数量的不同类型元素
val tuple2: (String, Int) = ("Alice", 25)
val tuple3: (String, Int, Boolean) = ("Bob", 30, true)
val tuple4: (Int, String, Double, Boolean) = (1, "test", 3.14, false)
// 访问元组元素
val name: String = tuple2._1 // "Alice"
val age: Int = tuple2._2 // 25
// 元组解构
val (personName, personAge) = tuple2
println(s"Name: $personName, Age: $personAge")
// 元组的方法
val swapped: (Int, String) = tuple2.swap // (25, "Alice")函数类型
scala
// 函数类型
val add: (Int, Int) => Int = (x, y) => x + y
val multiply: (Int, Int) => Int = _ * _
// 高阶函数类型
val applyTwice: (Int => Int, Int) => Int = (f, x) => f(f(x))
// 使用函数类型
val double: Int => Int = _ * 2
val result = applyTwice(double, 5) // 20
// 函数作为参数
def processNumbers(numbers: List[Int], operation: Int => Int): List[Int] = {
numbers.map(operation)
}
val numbers = List(1, 2, 3, 4, 5)
val doubled = processNumbers(numbers, _ * 2)
val squared = processNumbers(numbers, x => x * x)类型别名
scala
// 类型别名
type UserId = Int
type UserName = String
type UserData = (UserId, UserName, Int) // (id, name, age)
val user: UserData = (1, "Alice", 25)
// 复杂类型别名
type StringToInt = String => Int
type UserMap = Map[UserId, UserName]
val userMap: UserMap = Map(1 -> "Alice", 2 -> "Bob")
val parser: StringToInt = _.toInt泛型类型
scala
// 泛型类定义
class Container[T](val value: T) {
def get: T = value
def map[U](f: T => U): Container[U] = new Container(f(value))
}
// 使用泛型类
val intContainer = new Container(42)
val stringContainer = new Container("Hello")
val doubledContainer = intContainer.map(_ * 2)
// 泛型方法
def identity[T](x: T): T = x
def pair[A, B](a: A, b: B): (A, B) = (a, b)
val id1 = identity(42) // Int
val id2 = identity("hello") // String
val p = pair("key", 100) // (String, Int)类型推断
scala
// Scala 的类型推断
val number = 42 // 推断为 Int
val text = "Hello" // 推断为 String
val flag = true // 推断为 Boolean
val decimal = 3.14 // 推断为 Double
val list = List(1, 2, 3) // 推断为 List[Int]
val map = Map("a" -> 1) // 推断为 Map[String, Int]
// 需要显式类型注解的情况
val emptyList: List[String] = List() // 无法推断元素类型
val recursive: Int => Int = x => if (x <= 0) 1 else x * recursive(x - 1)类型检查和转换
scala
// 类型检查
val obj: Any = "Hello, World!"
val isString: Boolean = obj.isInstanceOf[String]
val isInt: Boolean = obj.isInstanceOf[Int]
// 类型转换
if (obj.isInstanceOf[String]) {
val str: String = obj.asInstanceOf[String]
println(str.toUpperCase)
}
// 安全的类型转换
obj match {
case s: String => println(s"String: ${s.toUpperCase}")
case i: Int => println(s"Integer: ${i * 2}")
case _ => println("Unknown type")
}Nothing 和 Null 类型
scala
// Nothing: 所有类型的子类型,表示永不返回
def error(message: String): Nothing = {
throw new RuntimeException(message)
}
def divide(x: Int, y: Int): Int = {
if (y == 0) error("Division by zero")
else x / y
}
// Null: 所有引用类型的子类型
val nullString: String = null // 不推荐使用
val nullList: List[Int] = null // 不推荐使用
// 使用 Option 代替 null
def safeDivide(x: Int, y: Int): Option[Int] = {
if (y == 0) None else Some(x / y)
}实际应用示例
类型安全的配置系统
scala
// 定义配置类型
sealed trait ConfigValue
case class StringConfig(value: String) extends ConfigValue
case class IntConfig(value: Int) extends ConfigValue
case class BooleanConfig(value: Boolean) extends ConfigValue
class Configuration {
private var configs: Map[String, ConfigValue] = Map()
def set(key: String, value: ConfigValue): Unit = {
configs = configs + (key -> value)
}
def getString(key: String): Option[String] = {
configs.get(key).collect {
case StringConfig(value) => value
}
}
def getInt(key: String): Option[Int] = {
configs.get(key).collect {
case IntConfig(value) => value
}
}
def getBoolean(key: String): Option[Boolean] = {
configs.get(key).collect {
case BooleanConfig(value) => value
}
}
}
// 使用示例
val config = new Configuration()
config.set("app.name", StringConfig("MyApp"))
config.set("app.port", IntConfig(8080))
config.set("app.debug", BooleanConfig(true))
val appName = config.getString("app.name").getOrElse("DefaultApp")
val port = config.getInt("app.port").getOrElse(3000)
val debug = config.getBoolean("app.debug").getOrElse(false)类型安全的 JSON 处理
scala
// 简化的 JSON 类型
sealed trait Json
case object JsonNull extends Json
case class JsonBoolean(value: Boolean) extends Json
case class JsonNumber(value: Double) extends Json
case class JsonString(value: String) extends Json
case class JsonArray(values: List[Json]) extends Json
case class JsonObject(fields: Map[String, Json]) extends Json
// JSON 构建器
object Json {
def obj(fields: (String, Json)*): JsonObject = JsonObject(fields.toMap)
def arr(values: Json*): JsonArray = JsonArray(values.toList)
def str(value: String): JsonString = JsonString(value)
def num(value: Double): JsonNumber = JsonNumber(value)
def bool(value: Boolean): JsonBoolean = JsonBoolean(value)
val `null`: JsonNull.type = JsonNull
}
// 使用示例
val json = Json.obj(
"name" -> Json.str("Alice"),
"age" -> Json.num(25),
"active" -> Json.bool(true),
"hobbies" -> Json.arr(
Json.str("reading"),
Json.str("swimming")
),
"address" -> Json.obj(
"city" -> Json.str("New York"),
"zipcode" -> Json.str("10001")
)
)练习
练习 1:类型转换和检查
scala
object TypeExercise {
def processValue(value: Any): String = {
value match {
case i: Int if i > 0 => s"Positive integer: $i"
case i: Int if i < 0 => s"Negative integer: $i"
case i: Int => "Zero"
case s: String if s.nonEmpty => s"Non-empty string: $s"
case s: String => "Empty string"
case b: Boolean => s"Boolean: $b"
case d: Double => f"Double: $d%.2f"
case _ => "Unknown type"
}
}
def main(args: Array[String]): Unit = {
val values: List[Any] = List(42, -10, 0, "Hello", "", true, 3.14159, 'A')
values.foreach(v => println(processValue(v)))
}
}练习 2:Option 类型应用
scala
object OptionExercise {
case class Person(name: String, age: Int, email: Option[String])
val people = List(
Person("Alice", 25, Some("alice@example.com")),
Person("Bob", 30, None),
Person("Charlie", 35, Some("charlie@example.com"))
)
def findPersonByName(name: String): Option[Person] = {
people.find(_.name == name)
}
def getEmailDomain(person: Person): Option[String] = {
person.email.map(_.split("@").last)
}
def main(args: Array[String]): Unit = {
val alice = findPersonByName("Alice")
val domain = alice.flatMap(getEmailDomain)
println(s"Alice's email domain: ${domain.getOrElse("No email")}")
// 链式操作
val result = for {
person <- findPersonByName("Charlie")
email <- person.email
domain = email.split("@").last
} yield s"${person.name}'s domain is $domain"
println(result.getOrElse("Person not found or no email"))
}
}总结
本章详细介绍了 Scala 的数据类型系统:
- 类型层次结构:Any、AnyVal、AnyRef 的关系
- 基本类型:数值、字符、布尔、Unit 类型
- 引用类型:字符串、集合、Option 等
- 复合类型:元组、函数类型
- 类型系统特性:泛型、类型推断、类型检查
- 特殊类型:Nothing、Null 的使用场景
理解 Scala 的类型系统是掌握这门语言的关键。在下一章中,我们将学习 Scala 字面量,深入了解各种数据的字面量表示方法。