跳到主要内容

Kotlin 数据类

提示
  1. 数据类定义:Kotlin 的数据类使用 data 关键字定义,主要用于存储数据。它们自动实现基本功能,如 copy()equals()hashCode()toString(),以及 componentN() 函数。
  2. 构造函数要求:数据类的主构造函数必须至少有一个参数,这些参数需要用 valvar 定义。数据类不能是 open、abstract、inner 或 sealed 类。
  3. 数据类的特性和函数:数据类自动生成 copy() 方法用于创建对象副本,equals()hashCode() 用于对象比较,toString() 方法提供字符串表示形式,而解构声明允许将对象属性分解为多个变量。

在某些情况下,你可能需要创建一个仅用于存放数据的类。在这些情况下,你可以将类标记为 data 来创建一个数据类。例如,

data class Person(val name: String, var age: Int)

对于这个类,编译器会自动生成:

  • 基于主构造函数的 copy() 函数、equals()hashCode() 配对,以及 toString() 形式
  • componentN() 函数

在详细讨论这些特性之前,让我们先了解一下数据类必须满足的要求。

Kotlin 数据类要求

以下是要求:

  • 主构造函数必须至少有一个参数。
  • 主构造函数的参数必须被标记为 val(只读)或 var(可读写)。
  • 类不能是 open、abstract、inner 或 sealed。
  • 类可以扩展其他类或实现接口。如果你使用的是 1.1 之前的 Kotlin 版本,类只能实现接口。

示例:Kotlin 数据类

data class User(val name: String, val age: Int)

fun main(args: Array<String>) {
val jack = User("jack", 29)
println("姓名 = ${jack.name}")
println("年龄 = ${jack.age}")
}

当你运行程序时,输出将是:

姓名 = jack
年龄 = 29

当你声明一个数据类时,编译器会在幕后自动生成诸如 toString()equals()hashcode() 等多个函数。这有助于保持代码简洁。如果你使用 Java,你将需要编写大量样板代码。

让我们使用这些函数:

复制

对于数据类,你可以使用 copy() 函数创建一个对象的副本,并更改其中的某些属性。以下是它的工作方式:

data class User(val name: String, val age: Int)

fun main(args: Array<String>) {
val u1 = User("John", 29)

// 使用 copy 函数创建对象
val u2 = u1.copy(name = "Randy")

println("u1: 姓名 = ${u1.name}, 年龄 = ${u1.age}")
println("u2: 姓名 = ${u2.name}, 年龄 = ${u2.age}")
}

当你运行程序时,输出将是:

u1: 姓名 = John, 年龄 = 29
u2: 姓名 = Randy, 年龄 = 29

toString() 方法

toString() 函数返回对象的字符串表示。

data class User(val name: String, val age: Int)

fun main(args: Array<String>) {
val u1 = User("John", 29)
println(u1.toString())
}

当你运行程序时,输出将是:

User(姓名=John, 年龄=29)

hashCode() 和 equals()

hasCode() 方法返回对象的哈希码。如果两个对象相等,hashCode() 产生相同的整数结果。推荐阅读: hashCode()

equals() 返回 true 如果两个对象相等(具有相同的 hashCode())。如果对象不相等,equals() 返回 false推荐阅读: equals()

数据类 User(val name: String, val age: Int)

fun main(args: Array<String>) {
val u1 = User("John", 29)
val u2 = u1.copy()
val u3 = u1.copy(name = "Amanda")

println("u1 的哈希码 = ${u1.hashCode()}")
println("u2 的哈希码 = ${u2.hashCode()}")
println("u3 的哈希码 = ${u3.hashCode()}")

if (u1.equals(u2) == true)
println("u1 等于 u2。")
else
println("u1 不等于 u2。")

if (u1.equals(u3) == true)
println("u1 等于 u3。")
else
println("u1 不等于 u3。")
}

当你运行程序时,输出将是:

u1 的哈希码 = 71750738
u2 的哈希码 = 71750738
u3 的哈希码 = 771732263
u1 等于 u2。
u1 不等于 u3。

解构声明

你可以使用解构声明将一个对象分解为多个变量。例如:

data class User(val name: String, val age: Int, val gender: String)

fun main(args: Array<String>) {
val u1 = User("John", 29, "Male")

val (name, age, gender) = u1
println("姓名 = $name")
println("年龄 = $age")
println("性别 = $gender")
}

当你运行程序时,输出将是:

姓名 = John
年龄 = 29
性别 = Male

这是因为编译器为数据类的所有属性生成了 componentN() 函数。例如:

data class User(val name: String, val age: Int, val gender: String)

fun main(args: Array<String>) {
val u1 = User("John", 29, "Male")

println(u1.component1()) // John
println(u1.component2()) // 29
println(u1.component3()) // "Male"
}

当你运行程序时,输出将是:

John
29
Male