User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • Zookeeper
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • Python
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MinIO
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • Kafka
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
    • 摘要
    • 杂图
    • 问题随笔
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud Alibaba - 指南
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin中文版
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
    • GO相关文档
    • Go学习导航
    • GoCN社区
    • GO极客兔兔-案例
    • 讯飞星火GPT
    • Hollis博客
    • PostgreSQL德哥
    • 优质博客推荐
    • 半兽人大佬
    • 系列教程
    • PostgreSQL文章
    • 云原生资料库
    • 并发博客大佬
Help?

Please contact us on our email for need any support

Support
    首页   ›   Kotlin   ›   Kotlin Notes   ›   正文
Kotlin Notes

Kotlin-类型进阶—数据类(二十四)

2021-01-27 00:18:13
703  0 0
参考目录 隐藏
1) 数据类
2) component(解构)
3) copy() 函数 – 复制
4) toString()方法 – 返回字符串
5) hashCode() 和 equals()
6) 对比JavaBean
7) 合理使用 data class

阅读完需:约 6 分钟

数据类

数据类是一个简单的类,用于保存数据/状态并包含标准功能(函数)。 data关键字用于将类声明为数据类。

data class User(val name: String, val age: Int)

声明数据类必须至少包含一个带有属性参数(val或var)的主构造函数。

数据类内部有以下函数:

  • equals(): Boolean
  • hashCode(): Int
  • toString(): String
  • component() 函数对应的属性
  • copy()

要创建数据类,首先需要满足以下要求:

  • 包含具有至少一个参数的主构造函数。
  • 主构造函数的参数标记为val或var。
  • 数据类不能是抽象的,内部的,开放的或密封的。
  • 在1.1版本之前,数据类只实现接口。1.1版本之后,数据类可以扩展其他类。

由于数据类内部存在上述函数,因此数据类消除了反复套用代码。

java 中的javaBean 和 kotlin 的data class 看似很类似,但是这两个不相等的。

在 data class 中有很多方法:

component(解构)

可以使用解构声明将一个对象分解为多个变量

例子:

data class User(val name: String, val age: Int, val gender: String)

fun main(args: Array<String>) {
    val u1 = User("John", 29, "Male")

    val (name, age, gender) = u1
    println("name = $name")
    println("age = $age")
    println("gender = $gender")
}

运行该程序时,输出为:

name = John
age = 29
gender = Male

这是可能的,因为编译器会为数据类生成component()函数的所有属性。 例如:

data class User(val name: String, val age: Int, val gender: String)

fun main(args: Array<String>) {
    val u1 = User("John", 29, "Male")

    println(u1.component1())     // John
    println(u1.component2())     // 29  
    println(u1.component3())     // "Male"
}

运行该程序时,输出为:

John
29
Male

copy() 函数 – 复制

对于数据类,可以使用copy()函数创建具有不同属性的对象副本。 它的工作原理如下:

data class User(val name: String, val age: Int)

fun main(args: Array<String>) {
    val u1 = User("John", 29)
   
    //使用复制函数创建对象
    val u2 = u1.copy(name = "Randy")

    println("u1: name = ${u1.name}, name = ${u1.age}")
    println("u2: name = ${u2.name}, name = ${u2.age}")
}

运行该程序时,输出为:

u1: name = John, name = 29
u2: name = Randy, name = 29

toString()方法 – 返回字符串

oString()函数返回该对象的字符串表示形式。

data class User(val name: String, val age: Int)

fun main(args: Array<String>) {
    val u1 = User("John", 29)
    println(u1.toString())
}

运行该程序时,输出为:

User(name=John, age=29)

hashCode() 和 equals()

hasCode() 方法返回对象的散列码。 如果两个对象相等,则hashCode()会产生相同的整数结果。

如果两个对象相等(hashCode()相同),则equals()返回true。如果对象不相等,equals()返回false。

data class User(val name: String, val age: Int)

fun main(args: Array<String>) {
    val u1 = User("John", 29)
    val u2 = u1.copy()
    val u3 = u1.copy(name = "Amanda")

    println("u1 hashcode = ${u1.hashCode()}")
    println("u2 hashcode = ${u2.hashCode()}")
    println("u3 hashcode = ${u3.hashCode()}")

    if (u1.equals(u2) == true)
        println("u1 等于 u2.")
    else
        println("u1 不等于 u2.")

    if (u1.equals(u3) == true)
        println("u1 等于 u3.")
    else
        println("u1 不等于 u3.")
}

运行该程序时,输出为:

u1 hashcode = 71750738
u2 hashcode = 71750738
u3 hashcode = 771732263
u1 等于 u2.
u1 不等于 u3.

对比JavaBean

data class不能被继承

可以先看一下kotlin为data类生成的对应的java类是什么样的,查看方式,doule shift键,然后Actions中输入kotlin Bytecode显示:

点击Decompile即可查看对应生成的java代码

以下是Book的数据类对应生成的java代码

val book = Book(0, "Kotlin in Action", Person(1, "Dmitry", 40))
public final class Book {
   private final long id;
   @NotNull
   private final String name;
   @NotNull
   private final Person author;

   public final long getId() {
      return this.id;
   }

   @NotNull
   public final String getName() {
      return this.name;
   }

   @NotNull
   public final Person getAuthor() {
      return this.author;
   }

   public Book(long id, @NotNull String name, @NotNull Person author) {
      Intrinsics.checkNotNullParameter(name, "name");
      Intrinsics.checkNotNullParameter(author, "author");
      super();
      this.id = id;
      this.name = name;
      this.author = author;
   }

   public final long component1() {
      return this.id;
   }

   @NotNull
   public final String component2() {
      return this.name;
   }

   @NotNull
   public final Person component3() {
      return this.author;
   }

   @NotNull
   public final Book copy(long id, @NotNull String name, @NotNull Person author) {
      Intrinsics.checkNotNullParameter(name, "name");
      Intrinsics.checkNotNullParameter(author, "author");
      return new Book(id, name, author);
   }

   // $FF: synthetic method
   public static Book copy$default(Book var0, long var1, String var3, Person var4, int var5, Object var6) {
      if ((var5 & 1) != 0) {
         var1 = var0.id;
      }

      if ((var5 & 2) != 0) {
         var3 = var0.name;
      }

      if ((var5 & 4) != 0) {
         var4 = var0.author;
      }

      return var0.copy(var1, var3, var4);
   }

   @NotNull
   public String toString() {
      return "Book(id=" + this.id + ", name=" + this.name + ", author=" + this.author + ")";
   }

   public int hashCode() {
      long var10000 = this.id;
      int var1 = (int)(var10000 ^ var10000 >>> 32) * 31;
      String var10001 = this.name;
      var1 = (var1 + (var10001 != null ? var10001.hashCode() : 0)) * 31;
      Person var2 = this.author;
      return var1 + (var2 != null ? var2.hashCode() : 0);
   }

   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof Book) {
            Book var2 = (Book)var1;
            if (this.id == var2.id && Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.author, var2.author)) {
               return true;
            }
         }

         return false;
      } else {
         return true;
      }
   }
}

除了类名方法名前面添加了final关键字以外,生成了许多方法,其中有重写hashCode()和equals()方法,所以如果有一个类继承了data类,可能导致属性变化,从而导致hashCode()和equals()方法的结果不一致。


合理使用 data class

data类的属性最好全部为基本类型或者其他data类型,保持它的纯净性。

另外,有方法可以破除data类的不可继承性,其实如果你想用一个可以继承到类,只需要把data关键字去掉,建一个普通类就好了。kotlin这样设计肯定是想保持它的纯洁性,如果可继承,只会变的更复杂。

破除data类的不可继承性需要额外添加两个插件:

plugins {	
	...
    id 'org.jetbrains.kotlin.plugin.noarg' version '1.4.20'
    id 'org.jetbrains.kotlin.plugin.allopen' version '1.4.20'
}

noArg {
    invokeInitializers = true
    annotations "com.bennyhuo.kotlin.advancedtypes.dataclasses.PoKo"
}

allOpen {
    annotations "com.bennyhuo.kotlin.advancedtypes.dataclasses.PoKo"
}

在data类上加注解即可

@PoKo
data class Book(val id: Long, val name: String, val author: Person)

这时同样去查看Book的数据类对应生成的java代码会发现,之前的类名和get方法名前面的final关键字被移除了,也就是可以被继承使用了,同时会生成一个无参的构造函数。

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

0 打赏
Enamiĝu al vi
不要为明天忧虑.因为明天自有明天的忧虑.一天的难处一天当就够了。
543文章 68评论 292点赞 582216浏览

随机文章
SpringMVC笔记3—组件介绍
5年前
SpringBoot—整合SpringSecurity(方法安全)
5年前
PostgreSQL—常用指令
3年前
MyBatisPlus—分页查询以及自定义sql分页
5年前
Redis笔记—String
5年前
博客统计
  • 日志总数:543 篇
  • 评论数目:68 条
  • 建站日期:2020-03-06
  • 运行天数:1904 天
  • 标签总数:23 个
  • 最后更新:2024-12-20
Copyright © 2025 网站备案号: 浙ICP备20017730号 身体没有灵魂是死的,信心没有行为也是死的。
主页
页面
  • 归档
  • 摘要
  • 杂图
  • 问题随笔
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
543 文章 68 评论 582216 浏览
测试
测试
看板娘
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付