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演示

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335