kotlin语言学习11 ——kotlin的data class(数据类)

本节介绍kotlin的data class(数据类)

1、数据类的定义和反编译分析

在Java中数据类中具有的 getter,setter方法,可以通过 IDEA或者eclipse来生成代码,但是有很多的冗余
当然我们也可以使用Java的插件,lombok,仅用几个注释就能解决。

1.1、数据类的定义

但是在kotlin中,我们可以直接使用 data 关键字来定义数据类

注意数据类的前提条件:

  • 1、主构造方法至少要有一个参数
  • 2、所有的主构造方法参数都需要被标记为 var 或者 val
  • 3、数据类不能是抽象、open的、sealed(密封类)、inner的类

数据类的定义示例:

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

数据类的使用:

fun main() {
    val person = Person("zhangsan", 20, "beijing")
    println(person)  
}

1.2、数据类的反编译分析

接下来,我们可以使用反编译,对上面生成的数据类进行深度的分析。(关于反编译知识,看一看我之前的博客,点这里 ) ,以下是反编译结果:

    Compiled from "DataClass.kt"
    public final class com.liang.kotlin.basic.data_class.Person {
      public final java.lang.String getName();
        Code:
           0: aload_0
           1: getfield      #11                 // Field name:Ljava/lang/String;
           4: areturn

      public final int getAge();
        Code:
           0: aload_0
           1: getfield      #19                 // Field age:I
           4: ireturn

      public final void setAge(int);
        Code:
           0: aload_0
           1: iload_1
           2: putfield      #19                 // Field age:I
           5: return

      public final java.lang.String getAddress();
        Code:
           0: aload_0
           1: getfield      #26                 // Field address:Ljava/lang/String;
           4: areturn

      public final void setAddress(java.lang.String);
        Code:
           0: aload_1
           1: ldc           #29                 // String <set-?>
           3: invokestatic  #35                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
           6: aload_0
           7: aload_1
           8: putfield      #26                 // Field address:Ljava/lang/String;
          11: return

      public com.liang.kotlin.basic.data_class.Person(java.lang.String, int, java.lang.String);
        Code:
           0: aload_1
           1: ldc           #38                 // String name
           3: invokestatic  #35                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
           6: aload_3
           7: ldc           #39                 // String address
           9: invokestatic  #35                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
          12: aload_0
          13: invokespecial #42                 // Method java/lang/Object."<init>":()V
          16: aload_0
          17: aload_1
          18: putfield      #11                 // Field name:Ljava/lang/String;
          21: aload_0
          22: iload_2
          23: putfield      #19                 // Field age:I
          26: aload_0
          27: aload_3
          28: putfield      #26                 // Field address:Ljava/lang/String;
          31: return

      public final java.lang.String component1();
        Code:
           0: aload_0
           1: getfield      #11                 // Field name:Ljava/lang/String;
           4: areturn

      public final int component2();
        Code:
           0: aload_0
           1: getfield      #19                 // Field age:I
           4: ireturn

      public final java.lang.String component3();
        Code:
           0: aload_0
           1: getfield      #26                 // Field address:Ljava/lang/String;
           4: areturn

      public final com.liang.kotlin.basic.data_class.Person copy(java.lang.String, int, java.lang.String);
        Code:
           0: aload_1
           1: ldc           #38                 // String name
           3: invokestatic  #35                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
           6: aload_3
           7: ldc           #39                 // String address
           9: invokestatic  #35                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
          12: new           #2                  // class com/liang/kotlin/basic/data_class/Person
          15: dup
          16: aload_1
          17: iload_2
          18: aload_3
          19: invokespecial #49                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
          22: areturn

      public static com.liang.kotlin.basic.data_class.Person copy$default(com.liang.kotlin.basic.data_class.Person, java.lang.String, int, java.lang.String, int, java.lang.Object);
        Code:
           0: iload         4
           2: iconst_1
           3: iand
           4: ifeq          12
           7: aload_0
           8: getfield      #11                 // Field name:Ljava/lang/String;
          11: astore_1
          12: iload         4
          14: iconst_2
          15: iand
          16: ifeq          24
          19: aload_0
          20: getfield      #19                 // Field age:I
          23: istore_2
          24: iload         4
          26: iconst_4
          27: iand
          28: ifeq          36
          31: aload_0
          32: getfield      #26                 // Field address:Ljava/lang/String;
          35: astore_3
          36: aload_0
          37: aload_1
          38: iload_2
          39: aload_3
          40: invokevirtual #53                 // Method copy:(Ljava/lang/String;ILjava/lang/String;)Lcom/liang/kotlin/basic/data_class/Person;
          43: areturn

      public java.lang.String toString();
        Code:
           0: new           #56                 // class java/lang/StringBuilder
           3: dup
           4: invokespecial #57                 // Method java/lang/StringBuilder."<init>":()V
           7: ldc           #59                 // String Person(name=
           9: invokevirtual #63                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          12: aload_0
          13: getfield      #11                 // Field name:Ljava/lang/String;
          16: invokevirtual #63                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          19: ldc           #65                 // String , age=
          21: invokevirtual #63                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          24: aload_0
          25: getfield      #19                 // Field age:I
          28: invokevirtual #68                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
          31: ldc           #70                 // String , address=
          33: invokevirtual #63                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          36: aload_0
          37: getfield      #26                 // Field address:Ljava/lang/String;
          40: invokevirtual #63                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          43: ldc           #72                 // String )
          45: invokevirtual #63                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          48: invokevirtual #74                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          51: areturn

      public int hashCode();
        Code:
           0: aload_0
           1: getfield      #11                 // Field name:Ljava/lang/String;
           4: dup
           5: ifnull        14
           8: invokevirtual #77                 // Method java/lang/Object.hashCode:()I
          11: goto          16
          14: pop
          15: iconst_0
          16: bipush        31
          18: imul
          19: aload_0
          20: getfield      #19                 // Field age:I
          23: invokestatic  #82                 // Method java/lang/Integer.hashCode:(I)I
          26: iadd
          27: bipush        31
          29: imul
          30: aload_0
          31: getfield      #26                 // Field address:Ljava/lang/String;
          34: dup
          35: ifnull        44
          38: invokevirtual #77                 // Method java/lang/Object.hashCode:()I
          41: goto          46
          44: pop
          45: iconst_0
          46: iadd
          47: ireturn

      public boolean equals(java.lang.Object);
        Code:
           0: aload_0
           1: aload_1
           2: if_acmpeq     56
           5: aload_1
           6: instanceof    #2                  // class com/liang/kotlin/basic/data_class/Person
           9: ifeq          58
          12: aload_1
          13: checkcast     #2                  // class com/liang/kotlin/basic/data_class/Person
          16: astore_2
          17: aload_0
          18: getfield      #11                 // Field name:Ljava/lang/String;
          21: aload_2
          22: getfield      #11                 // Field name:Ljava/lang/String;
          25: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
          28: ifeq          58
          31: aload_0
          32: getfield      #19                 // Field age:I
          35: aload_2
          36: getfield      #19                 // Field age:I
          39: if_icmpne     58
          42: aload_0
          43: getfield      #26                 // Field address:Ljava/lang/String;
          46: aload_2
          47: getfield      #26                 // Field address:Ljava/lang/String;
          50: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
          53: ifeq          58
          56: iconst_1
          57: ireturn
          58: iconst_0
          59: ireturn
    }

通过上面的反编译,我们可以清楚的看到:
编译器做增加了一下内容:

1、equals/hasCode
2、toString(),形式为:Person(name=..., age=..., address=...)
3、针对属性的componentN方法,并且是按照属性的声明顺序来生成的
4、copy方法

2、数据类方法说明

通过上面的反编译class,接下来对编译器生成出来的函数进行探索。

2.1、componentN()

componentN的方法主要在于,解构声明:

  • 解构:在主构造方法中有多少个参数就会生成多少个 component方法 (component1,component2... )
  • 这些方法返回对应字段的值,component方法是用来实现 解构声明的

演示如图所示:

componentN演示

2.2、copy()

copy() : 作用在赋值的时候,很方便,
在Java中,一个对象的类成员如果如果被另一个对象复制,仅仅修改了一个参数,那么需要把这个对象的所有值都赋值给另一个对象,这样是非常麻烦的。
在kotlin中,可以通过copy()方法执行修改某一个参数
注意: 如果不加参数名字,那么默认是第一个,必须明确参数名

compy演示

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。