我正在参加「启航方案」
Kotlin是由JetBrains开发的针对JVM、Android和浏览器的静态编程言语,是Android的官方言语。Kotlin拥有较多高档而又简练的语法特性,提升了咱们的开发效率,减少了代码量。
在运用 java 的时分,咱们在用class界说一个entity时除了写get、set办法(运用Kotlin后省了这部分工作),经常还会重写类的 equals
、hashCode
和toString
办法,这些办法往往都是模板化的。在 kotlin 中供给了data class
搞定这些模版化代码。
data class与class的差异:
完成办法
- class类
class ClassUser(val name: String, var age: Int)
- data class类
data class DataClassUser(val name: String, var age: Int)
主动重写toString
办法
- data类的
toString
办法会打印出特点的值 - 非data类的
toString
办法则打印出内存地址val classUser = ClassUser("classuser", 18) val dataClassUser = DataClassUser("dataclassuser", 20) println("ClassUser -> ${classUser.toString()}") // ClassUser -> com.imock.vicjava.keyuse.ClassUser@11026067 println("DataClassUser -> ${dataClassUser.toString()}") // DataClassUser -> DataClassUser(name=dataclassuser, age=20)
新增componentN
办法
- data类新增特点的
componentN
办法,component1
代表第一个特点,component2
代表第二个特点。(常用于解构声明)val dataClassUser = DataClassUser("dataclassuser", 20) println("DataClassUser component1() -> ${dataClassUser.component1()}") // DataClassUser component1() -> dataclassuser println("DataClassUser component2() -> ${dataClassUser.component2()}") // DataClassUser component2() -> 20
新增copy
办法
- data类新增
copy
办法,能够用来修正部分特点,可是坚持其他不变。val dataClassUser = DataClassUser("dataclassuser", 20) println("ClassUser toString() -> ${classUser.toString()}") // DataClassUser -> DataClassUser(name=dataclassuser, age=20) val newDataClassUser = dataClassUser.copy(age = 22) println("DataClassUser copy -> ${newDataClassUser.toString()}") // DataClassUser copy -> DataClassUser(name=dataclassuser, age=22)
重写hashCode
和 equals
办法
- data类重写
hashCode
办法,equals
办法能够稍后看下源码,先判断两个是否是同一个目标,假如不是则进行类型判断,是相同类型则逐一比较特点的值。val classUserLisa1 = ClassUser("lisa", 20) val classUserLisa2 = ClassUser("lisa", 20) println("ClassUser equals -> ${classUserLisa1.equals(classUserLisa2)}") // ClassUser equals -> false println("classUserLisa1 hashCode -> ${classUserLisa1.hashCode()}") // classUserLisa1 hashCode -> 2081652693 println("classUserLisa2 hashCode -> ${classUserLisa2.hashCode()}") // classUserLisa2 hashCode -> 406765571 val dataClassUserLisa1 = DataClassUser("lisa", 20) val dataClassUserLisa2 = DataClassUser("lisa", 20) println("DataClassUser equals -> ${dataClassUserLisa1.equals(dataClassUserLisa2)}") // DataClassUser equals -> true println("dataClassUserLisa1 hashCode -> ${dataClassUserLisa1.hashCode()}") // dataClassUserLisa1 hashCode -> 102981865 println("dataClassUserLisa2 hashCode -> ${dataClassUserLisa2.hashCode()}") // dataClassUserLisa2 hashCode -> 102981865
data class为何如此奇特
data class DataClassUser(val name: String, var age: Int)
class ClassUser(var name: String, var age: Int)
独自看完成上两者没有太大的差异,一个运用data class,一个运用class,为何data class却多出那么多才能?得益于Kotlin高档的语法特性。咱们都知道kotlin终究仍是要编译成 java class 在JVM上运行的,为了更好的理解Kotlin高档而又简练的语法特性,有时咱们需求看看用kotlin写完的代码编译后是什么样子。Talk is cheap, show me the code.
class类编译后的java代码
Kotlin写法如下:
class ClassUser(var name: String, var age: Int)
检查编译后的java代码如下,能够看到帮咱们主动生成了get、set和结构办法:
public final class ClassUser {
@NotNull
private final String name;
private int age;
@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 ClassUser(@NotNull String name, int age) {
Intrinsics.checkNotNullParameter(name, "name");
super();
this.name = name;
this.age = age;
}
}
data class类编译后的java代码
Kotlin写法如下:
data class DataClassUser(val name: String, var age: Int)
检查其编译后的java代码如下,会发现比class类编译后的代码多了部分办法,新增了components
和copy
办法,重写了equals
、hashCode
和toString
办法。
public final class DataClassUser {
@NotNull
private final String name;
private int age;
@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 DataClassUser(@NotNull String name, int age) {
Intrinsics.checkNotNullParameter(name, "name");
super();
this.name = name;
this.age = age;
}
// 新增办法
@NotNull
public final String component1() {
return this.name;
}
// 新增办法
public final int component2() {
return this.age;
}
// 新增办法
@NotNull
public final DataClassUser copy(@NotNull String name, int age) {
Intrinsics.checkNotNullParameter(name, "name");
return new DataClassUser(name, age);
}
// 新增办法
// $FF: synthetic method
public static DataClassUser copy$default(DataClassUser var0, String var1, int var2, int var3, Object var4) {
if ((var3 & 1) != 0) {
var1 = var0.name;
}
if ((var3 & 2) != 0) {
var2 = var0.age;
}
return var0.copy(var1, var2);
}
// 重写该办法
@NotNull
public String toString() {
return "DataClassUser(name=" + this.name + ", age=" + this.age + ")";
}
// 重写该办法
public int hashCode() {
String var10000 = this.name;
return (var10000 != null ? var10000.hashCode() : 0) * 31 + Integer.hashCode(this.age);
}
// 重写该办法
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof DataClassUser) {
DataClassUser var2 = (DataClassUser)var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age) {
return true;
}
}
return false;
} else {
return true;
}
}
}
总结
知道data class
干了啥
- 重写
toString
办法。 - 新增
componentN
办法(component1()、component2()、...、componentN()
),其对应特点的声明顺序(常用于解构声明)。 - 新增
copy
办法,能够用来修正部分特点,可是坚持其他不变。
特别提下copy办法,可能有些同学疑问很少见到这个办法运用场景,慢慢地等你用上了MVI框架就知道State有必要运用 Kotlindata class,copy办法的应用自然少不了。 - 重写
equals
和hasCode
办法,equals()
办法不再单一比较目标引用,而是先判断两个是否是同一个目标,假如不是则进行类型判断,是相同类型则逐一比较特点的值。
运用data class
需求留意啥
- 主结构函数有必要要至少有一个参数。
- 主结构函数中的所有参数有必要被标记为val或者var。
- 数据类不能有以下修饰符:abstract、inner、open、sealed。