数据类是一个简单的类,用于保存数据/状态并包含标准功能(函数)。 data
关键字用于将类声明为数据类。
data class User(val name: String, val age: Int)
声明数据类必须至少包含一个带有属性参数(val
或var
)的主构造函数。
数据类内部有以下函数:
equals(): Boolean
hashCode(): Int
toString(): String
component()
函数对应的属性copy()
由于数据类内部存在上述函数,因此数据类消除了反复套用代码。
*Java数据类和Kotlin数据类的比较
如果想使用数据类在Java中创建用户数据项,则需要大量反复套用的代码。
import java.util.Objects; public class User { private String name; private int id; private String email; public User(String name, int id, String email) { this.name = name; this.id = id; this.email = email; } public String getName() { return name; } public void setName(String name) { this.name = name; } public intgetId() { return id; } public void setId(int id) { this.id = id; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; User user = (User) o; return getId() == user.getId() && Objects.equals(getName(), user.getName()) && Objects.equals(getEmail(), user.getEmail()); } @Override public inthashCode() { return Objects.hash(getName(), getId(), getEmail()); } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", id=" + id + ", email='" + email + '\'' + '}'; } }
使用User
类的对象,调用上述Java数据类的构造函数,如下所示 -
class MyClass{ public static void main(String agrs[]){ User u = new User("Susen",10010,"zyiz@mail.com"); System.out.println(u); } }
执行上面示例代码,得到以下结果 -
User{name='Susen', id=10010, email='zyiz@mail.com'}
上述Java数据类代码在Kotlin数据代码中使用一行重写完事 -
data class User(var name: String, var id: Int, var email: String)
使用User
类的对象调用上述Kotlin数据类的构造函数 -
data class User(var name: String, var id: Int, var email: String) fun main(agrs: Array<String>) { val u = User("Maxsu", 10010, "maxsu@zyiz.net") println(u) }
执行上面示例代码,得到以下结果 -
User{name='Maxsu', id=10010, email='maxsu@zyiz.net'}
要创建数据类,首先需要满足以下要求:
val
或var
。1.1
版本之前,数据类只实现接口。1.1
版本之后,数据类可以扩展其他类。Kotlin数据类仅关注数据而非代码实现。
下面来看一个没有数据类的简单程序。 在这个类中,尝试使用对象打印Product
类的引用。
class Product(varitem: String, var price: Int) fun main(agrs: Array<String>) { val p = Product("Thinkpad", 5600) println(p) }
在打印Product
类的引用时,它会显示类名为Product
的hashCode()
。它不打印对象属性的数据。
执行上面示例代码,得到以下结果 -
Product@5e2de80c
上述程序使用数据类(data class
)重写,打印Product
类的引用并显示对象的数据。上面代码中之所以发生这种情况,是因为数据类内部包含toString()
方法,它默认只是显示对象的字符串表示形式。
data class Product(var item: String, var price: Int) fun main(agrs: Array<String>) { val p = Product("Thinkpad", 5600) println(p) }
执行上面示例代码,得到以下结果 -
Product(item=Thinkpad, price=5600)
equal()
方法用于检查其他对象是否“等于”当前对象。 在两个或多个hashCode()
之间进行比较时,如果hashCode()
相等,则equals()
方法返回true
,否则返回false
。
例如,让我们看一个例子,一个普通类比较具有相同数据的Product
类的两个引用。
class Product(var item: String, var price: Int) fun main(agrs: Array<String>) { val p1 = Product("Thinkpad", 5000) val p2 = Product("Thinkpad", 5000) println(p1==p2) println(p1.equals(p2)) }
在上述程序中,引用p1
和引用p2
具有不同的引用。 由于p1
和p2
中的引用值不同,所以进行比较结果为false
。
执行上面示例代码,得到以下结果 -
false false
上述程序使用数据类重写,打印Product
类的引用并显示对象的数据。hashCode()
方法返回对象的哈希码。 如果两个对象相等,则hashCode()
会产生相同的整数结果。
data class Product(var item: String, var price: Int) fun main(agrs: Array<String>) { val p1 = Product("Thinkpad", 5000) val p2 = Product("Thinkpad", 5000) println(p1==p2) println(p1.equals(p2)) }
执行上面示例代码,得到以下结果 -
true true
数据类提供了一个copy()
方法,用于创建对象的副本(或冒号)。 使用copy()
方法,可以更改对象的部分或全部属性。
示例:
data class Product(var item: String, var price: Int) fun main(agrs: Array<String>) { val p1 = Product("Thinkpad", 5000) println("p1 包含数据为: $p1") val p2 = p1.copy() println("p2 拷贝对象包含p1的默认数据为:: $p2") val p3 = p1.copy(price = 20000) println("p3 包含 p1 和修改后的数据为 : $p3") }
执行上面示例代码,得到以下结果 -
p1 包含数据为: Product(item=Thinkpad, price=5000) p2 拷贝对象包含p1的默认数据为:: Product(item=Thinkpad, price=5000) p3 包含 p1 和修改后的数据为 : Product(item=Thinkpad, price=20000)
还可以在数据类的主构造函数中分配默认参数。 如果需要,可以稍后在程序中更改这些默认值。
示例:
data class Product(var item: String = "Apple Mac", var price: Int = 15000) fun main(agrs: Array<String>) { val p1 = Product(price = 20000) println(p1) }
执行上面示例代码,得到以下结果 -
Product(item=Apple Mac, price=20000)