DataClass详解
1. 基本使用
data class 类名(成员变量){
类体
}
//1. data class 不能继承,也不能增加 open 关键字
//2. ()中成员变量即时成员变量还是构造函数参数(也就是必须有val或var)
//3. 不能有其他构造函数
//4. 类体可以省略
//示例:
data class Student (val name:String,var age:String)
2. data class与普通类对比
//data class
@Metadata(
mv = {1, 9, 0},
k = 1,
d1 = {"\u0000&\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\b\n\u0000\n\u0002\u0010\f\n\u0002\b\u000e\n\u0002\u0010\u000b\n\u0002\b\u0004\b\u0086\b\u0018\u00002\u00020\u0001B\u001d\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0005\u0012\u0006\u0010\u0006\u001a\u00020\u0007¢\u0006\u0002\u0010\bJ\t\u0010\u0011\u001a\u00020\u0003HÆ\u0003J\t\u0010\u0012\u001a\u00020\u0005HÆ\u0003J\t\u0010\u0013\u001a\u00020\u0007HÆ\u0003J'\u0010\u0014\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u00032\b\b\u0002\u0010\u0004\u001a\u00020\u00052\b\b\u0002\u0010\u0006\u001a\u00020\u0007HÆ\u0001J\u0013\u0010\u0015\u001a\u00020\u00162\b\u0010\u0017\u001a\u0004\u0018\u00010\u0001HÖ\u0003J\t\u0010\u0018\u001a\u00020\u0005HÖ\u0001J\t\u0010\u0019\u001a\u00020\u0003HÖ\u0001R\u001a\u0010\u0004\u001a\u00020\u0005X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\t\u0010\n\"\u0004\b\u000b\u0010\fR\u0011\u0010\u0002\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\r\u0010\u000eR\u0011\u0010\u0006\u001a\u00020\u0007¢\u0006\b\n\u0000\u001a\u0004\b\u000f\u0010\u0010¨\u0006\u001a"},
d2 = {"LStudent;", "", "name", "", "age", "", "sex", "", "(Ljava/lang/String;IC)V", "getAge", "()I", "setAge", "(I)V", "getName", "()Ljava/lang/String;", "getSex", "()C", "component1", "component2", "component3", "copy", "equals", "", "other", "hashCode", "toString", "KoltinDemo"}
)
public final class Student {
@NotNull
private final String name;
private int age;
private final char sex;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final void setAge(int var1) {
this.age = var1;
}
public final char getSex() {
return this.sex;
}
public Student(@NotNull String name, int age, char sex) {
Intrinsics.checkNotNullParameter(name, "name");
super();
this.name = name;
this.age = age;
this.sex = sex;
}
@NotNull
public final String component1() {
return this.name;
}
public final int component2() {
return this.age;
}
public final char component3() {
return this.sex;
}
@NotNull
public final Student copy(@NotNull String name, int age, char sex) {
Intrinsics.checkNotNullParameter(name, "name");
return new Student(name, age, sex);
}
// $FF: synthetic method
public static Student copy$default(Student var0, String var1, int var2, char var3, int var4, Object var5) {
if ((var4 & 1) != 0) {
var1 = var0.name;
}
if ((var4 & 2) != 0) {
var2 = var0.age;
}
if ((var4 & 4) != 0) {
var3 = var0.sex;
}
return var0.copy(var1, var2, var3);
}
@NotNull
public String toString() {
return "Student(name=" + this.name + ", age=" + this.age + ", sex=" + this.sex + ")";
}
public int hashCode() {
String var10000 = this.name;
return ((var10000 != null ? var10000.hashCode() : 0) * 31 + Integer.hashCode(this.age)) * 31 + Character.hashCode(this.sex);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Student) {
Student var2 = (Student)var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.sex == var2.sex) {
return true;
}
}
return false;
} else {
return true;
}
}
}
//普通类
@Metadata(
@Metadata(
mv = {1, 9, 0},
k = 1,
d1 = {"\u0000\u001e\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\b\n\u0000\n\u0002\u0010\f\n\u0002\b\n\u0018\u00002\u00020\u0001B\u001d\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0005\u0012\u0006\u0010\u0006\u001a\u00020\u0007¢\u0006\u0002\u0010\bR\u001a\u0010\u0004\u001a\u00020\u0005X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\t\u0010\n\"\u0004\b\u000b\u0010\fR\u0011\u0010\u0002\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\r\u0010\u000eR\u0011\u0010\u0006\u001a\u00020\u0007¢\u0006\b\n\u0000\u001a\u0004\b\u000f\u0010\u0010¨\u0006\u0011"},
d2 = {"LStudent;", "", "name", "", "age", "", "sex", "", "(Ljava/lang/String;IC)V", "getAge", "()I", "setAge", "(I)V", "getName", "()Ljava/lang/String;", "getSex", "()C", "KoltinDemo"}
)
public final class Student {
@NotNull
private final String name;
private int age;
private final char sex;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public final void setAge(int var1) {
this.age = var1;
}
public final char getSex() {
return this.sex;
}
public Student(@NotNull String name, int age, char sex) {
Intrinsics.checkNotNullParameter(name, "name");
super();
this.name = name;
this.age = age;
this.sex = sex;
}
}
将两种不同类转成java我们看到data class 构造函数 成员变量基本与普通class一样,但是多了几个函数,具体函如下:
- public String toString()
- public int hashCode()
- public boolean equals(@Nullable Object var1)
- public final Student copy(@NotNull String name, @NotNull String age)
- public static Student copy$default(Student var0, String var1, String var2, int var3, Object var4)
- public final String component1()
- public final String component2()
2.1. toString函数
public String toString() {
return "Student(name=" + this.name + ", age=" + this.age + ", sex=" + this.sex + ")";
}
转成java 我们看到toString实际上就是调用各个成员变量的toString函数并组成新的字符串
2.2. hashCode
public int hashCode() {
String var10000 = this.name;
return ((var10000 != null ? var10000.hashCode() : 0) * 31 + Integer.hashCode(this.age)) * 31 + Character.hashCode(this.sex);
}
转成java 我们看到hashCode实际上就是调用各个成员变量的hashCode函数并组成新hashCode
因为java常量池原因,以及kotlin一些类自身hashcode的实现,两个成员变量值一样的对象他们Hash一致。
2.3. equals
public boolean equals(@Nullable Object var1) {
if (this != var1) {//对比引用,如果是同一个直接返回true
if (var1 instanceof Student) { //对比类型
Student var2 = (Student)var1;
//引用类型调用equals对比,基础类型使用==对比值
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age && this.sex == var2.sex) {
return true;
}
}
return false;
} else {
return true;
}
}
// 示例
data class Student(val name: String, var age: Int, val sex: Char)
val studentA = Student(String("张三".toCharArray()), 15, '男')
val studentB = Student(String("张三".toCharArray()), 15, '男')
println(studentB===studentA) //返回false
println(studentB == studentA)//返回true
copy
public final Student copy(@NotNull String name, int age, char sex) {
Intrinsics.checkNotNullParameter(name, "name");
return new Student(name, age, sex);
}
//实际就是创建一个新对象
3. 使用注意事项
- 重写了hashcode,两个对象的hashcode对比可能一样。导致有的android库在创建型对象后也不会触发更新,如liveData
- 构造函数必须有一个参数
评论区