Kotlin常用的 Kotlin 类 ① ( 嵌套类 | 数据类 | 数据类 copy 函数 | 数据类解构声明 operator fun component1 | 数据类运算符重载 )

Posted 韩曙亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin常用的 Kotlin 类 ① ( 嵌套类 | 数据类 | 数据类 copy 函数 | 数据类解构声明 operator fun component1 | 数据类运算符重载 )相关的知识,希望对你有一定的参考价值。

文章目录





一、嵌套类



嵌套类 指的是 在 类 A定义 类 B , 一般是 类 B 对 类 A 有一定的作用 , 将 类 B 嵌套进 类 A 中 ; 格式如下 :

class A 
	class B 
	

类 A 中调用 B , 可以直接使用 B() 进行调用 ;

外部调用 类 B 时 , 可以使用 A.B() 的形式进行调用 ;


在 Java 中内部类有 成员内部类 , 静态嵌套类 , 方法内部类 , 匿名内部类 几种类型 ;

Kotlin 嵌套类 , 相当于 Java 中的 静态嵌套类 ;


代码示例 : 在下面的代码中 , 在 Person 类内部中定义 Student 嵌套类 , 在 外部使用 Person.Student 使用其内部的 Student 嵌套类 ;

open class Person(val name: String, val age: Int) 
    class Student(val school: String) 
        fun goSchool() 
            println("去 $school 上学")
        
    


fun main() 
    Person.Student("小学").goSchool()

执行结果 :

去 小学 上学




二、数据类



数据类型定义 : Kotlin 中的 数据类型 是 专门用于存储 数据的 类 , 一般该类中不定义 成员方法 ;

数据类信息 : 数据类 中 自动提供了 toString 实现 , 可以将数据转为 字符串 ;

数据类型对比 : == 运算符 对比两个数数据类对比的是引用地址 , equals 和 hashCode 函数 可以对比具体的数据值 ;


在 Kotlin 中 , 一般情况下 == 比较的是内容 , === 比较的是引用 ;

== 运算符相当于调用的是 equals 方法 , 只要重写了 equals 方法 , == 比较的就是内容 ;

在 Any 超类中 , 没有重写 equals 方法 , == 对比的是 引用地址 ;


数据类定义形式 :

data class 数据类类名(数据类型参数) 

代码示例 :

data class Student(var name: String, var age: Int)

fun main() 
    println(Student("Tom", 18))

    // 在 Kotlin 中 , 一般情况下 == 比较的是内容 , === 比较的是引用
    println(Student("Tom", 18) == Student("Tom", 18))

执行结果 : 定义上述数据类 , 打印该数据类实例对象 , 得到的不是地址信息 , 而是数据类的实际值 ;

Student(name=Tom, age=18)
true

查看字节码信息 , 双击 Shift , 选择 Show Kotlin Bytecode 选项 ,

Kotlin Bytecode 界面 中 , 选择 Decompile 选项 , 将 字节码数据 反编译为 Java 代码数据 ,

发现 Kotlin 编译器 Student 数据类 自动生成了一个 toString 方法 , 将其数据打印出来 ;

同时还 重写 Student 数据类 中的 equals 和 hashCode 函数 ;

// Student.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

@Metadata(
   mv = 1, 4, 2,
   bv = 1, 0, 3,
   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\\u0002\\b\\r\\n\\u0002\\u0010\\u000b\\n\\u0002\\b\\u0004\\b\\u0086\\b\\u0018\\u00002\\u00020\\u0001B\\u0015\\u0012\\u0006\\u0010\\u0002\\u001a\\u00020\\u0003\\u0012\\u0006\\u0010\\u0004\\u001a\\u00020\\u0005¢\\u0006\\u0002\\u0010\\u0006J\\t\\u0010\\u000f\\u001a\\u00020\\u0003HÆ\\u0003J\\t\\u0010\\u0010\\u001a\\u00020\\u0005HÆ\\u0003J\\u001d\\u0010\\u0011\\u001a\\u00020\\u00002\\b\\b\\u0002\\u0010\\u0002\\u001a\\u00020\\u00032\\b\\b\\u0002\\u0010\\u0004\\u001a\\u00020\\u0005HÆ\\u0001J\\u0013\\u0010\\u0012\\u001a\\u00020\\u00132\\b\\u0010\\u0014\\u001a\\u0004\\u0018\\u00010\\u0001HÖ\\u0003J\\t\\u0010\\u0015\\u001a\\u00020\\u0005HÖ\\u0001J\\t\\u0010\\u0016\\u001a\\u00020\\u0003HÖ\\u0001R\\u001a\\u0010\\u0004\\u001a\\u00020\\u0005X\\u0086\\u000e¢\\u0006\\u000e\\n\\u0000\\u001a\\u0004\\b\\u0007\\u0010\\b\\"\\u0004\\b\\t\\u0010\\nR\\u001a\\u0010\\u0002\\u001a\\u00020\\u0003X\\u0086\\u000e¢\\u0006\\u000e\\n\\u0000\\u001a\\u0004\\b\\u000b\\u0010\\f\\"\\u0004\\b\\r\\u0010\\u000e¨\\u0006\\u0017",
   d2 = "LStudent;", "", "name", "", "age", "", "(Ljava/lang/String;I)V", "getAge", "()I", "setAge", "(I)V", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "component1", "component2", "copy", "equals", "", "other", "hashCode", "toString", "KotlinDemo"
)
public final class Student 
   @NotNull
   private String name;
   private int age;

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

   public final void setName(@NotNull String var1) 
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   

   public final int getAge() 
      return this.age;
   

   public final void setAge(int var1) 
      this.age = var1;
   

   public Student(@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 Student copy(@NotNull String name, int age) 
      Intrinsics.checkNotNullParameter(name, "name");
      return new Student(name, age);
   

   // $FF: synthetic method
   public static Student copy$default(Student 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 "Student(name=" + this.name + ", age=" + this.age + ")";
   

   public int hashCode() 
      String var10000 = this.name;
      return (var10000 != null ? var10000.hashCode() : 0) * 31 + this.age;
   

   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) 
               return true;
            
         

         return false;
       else 
         return true;
      
   

// HelloKt.java
import kotlin.Metadata;

@Metadata(
   mv = 1, 4, 2,
   bv = 1, 0, 3,
   k = 2,
   d1 = "\\u0000\\b\\n\\u0000\\n\\u0002\\u0010\\u0002\\n\\u0000\\u001a\\u0006\\u0010\\u0000\\u001a\\u00020\\u0001¨\\u0006\\u0002",
   d2 = "main", "", "KotlinDemo"
)
public final class HelloKt 
   public static final void main() 
      Student var0 = new Student("Tom", 18);
      boolean var1 = false;
      System.out.println(var0);
   

   // $FF: synthetic method
   public static void main(String[] var0) 
      main();
   





三、数据类 copy 函数



Kotlin 编译器不仅为 数据类 重写了 toString , equals , hashCode 函数 , 还 提供了 copy 函数 , 借助该函数可以 快速创建一个相同内容的数据类 ;

特别注意 : 数据类 copy 函数调用的是主构造函数 , 如果数据类有属性是在次构造函数中赋值的 , 则该数据不会被 copy 函数复制 ;

在上个章节查看的 数据类 字节码 反编译后的 Java 代码 , 查看其 copy 函数 , 内容如下 :

   // $FF: synthetic method
   public static Student copy$default(Student 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);
   

代码示例 :

data class Student(var name: String, var age: Int)

fun main() 
    val student = Student("Tom", 18)
    println(student)

    // 拷贝数据类, name 属性设置为 Jerry
    val student2 = student.copy(name = "Jerry")
    println(student2)

执行结果 :

Student(name=Tom, age=18)
Student(name=Jerry, age=18)




四、数据类解构声明



在之前的博客 【Kotlin】集合操作 ③ ( List 集合遍历 | for in | forEach | forEachIndexed | List 通过解构一次性给多个元素赋值 ) 中介绍了 , 使用集合一次性给多个变量赋值 ;

Kotlin 普通类 和 数据类 都可以 支持 解构语法 , 为多个变量进行赋值 ;

数据类 自带 支持解构语法的特性 , 不需要使用 operator fun component1() 解构声明 ;


1、Kotlin 普通类解构声明 operator fun component1


在 普通 Kotlin 类中使用 如下声明 , 即可支持解构语法 ;

operator fun component1() = 成员属性名1
operator fun component2() = 成员属性名2
operator fun component3() = 成员属性名3
operator fun component4() = 成员属性名4
...
...

代码示例 :

class Student(var name: String, var age: Int) 
    operator fun component1() = name
    operator fun component2() = age


fun main() 
    val student = Student("Tom", 18)
    println(student)

    val (name, age) = student
    println("name = $name, age = $age")

执行结果 :

Student@61bbe9ba
name = Tom, age = 18

2、数据类解构声明


数据类 自带 支持解构语法的特性 , 不需要使用 operator fun component1() 解构声明 ;


代码示例 :

data class Student(var name: String, var age: Int)

fun main() 
    val student = Student("Tom", 18)
    println(student)

    val (name, age) = student
    println("name = $name, age = $age")

执行结果 :

Student(name=Tom, age=18)
name = Tom, age = 18

查看字节码信息 , 双击 Shift , 选择 Show Kotlin Bytecode 选项 ,

Kotlin Bytecode 界面 中 , 选择 Decompile 选项 , 将 字节码数据 反编译为 Java 代码数据 ,

反编译后的 Java 代码数据如下 :

// Student.java
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

@Metadata(
   mv = 1, 4, 2,
   bv = 1, 0, 3,
   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\\u0002\\b\\r\\n\\u0002\\u0010\\u000b\\n\\u0002\\b\\u0004\\b\\u0086\\b\\u0018\\u00002\\u00020\\u0001B\\u0015\\u0012\\u0006\\u0010\\u0002\\u001a\\u00020\\u0003\\u0012\\u0006\\u0010\\u0004\\u001a\\u00020\\u0005¢\\u0006\\u0002\\u0010\\u0006J\\t\\u0010\\u000f\\u001a\\u00020\\u0003HÆ\\u0003J\\t\\u0010\\u0010\\u001a\\u00020\\u0005HÆ\\u0003J\\u001d\\u0010\\u0011\\u001a\\u00020\\u00002\\b\\b\\u0002\\u0010\\u0002\\u001a\\u00020\\u00032\\b\\b\\u0002\\u0010\\u0004\\u001a\\u00020\\u0005HÆ\\u0001J\\u0013\\u0010\\u0012\\u001a\\u00020\\u00132\\b\\u0010\\u0014\\u001a\\u0004\\u0018\\u00010\\u0001HÖ\\u0003J\\t\\u0010\\u0015\\u001a\\u00020\\u0005HÖ\\u0001J\\t\\u0010\\u0016\\u001a\\u00020\\u0003HÖ\\u0001R\\u001a\\u0010\\u0004\\u001a\\u00020\\u0005X\\u0086\\u000e¢\\u0006\\u000e\\n\\u0000\\u001a\\u0004\\b\\u0007\\u0010\\b\\"\\u0004\\b\\t\\u0010\\nR\\u001a\\u0010\\u0002\\u001a\\u00020\\u0003X\\u0086\\u000e¢\\u0006\\u000e\\n\\u0000\\u001a\\u0004\\b\\u000b\\u0010\\f\\"\\u0004\\b\\r\\u0010\\u000e¨\\u0006\\u0017",
   d2 = "LStudent;", "", "name", "", "age", "", "(Ljava/lang/String;I)V", "getAge", "()I", "setAge", "(I)V", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "component1", "component2", "copy", "equals", "", "other", "hashCode", "toString", "KotlinDemo"
)
public final class Student 
   @NotNull
   private String name;
   private int age;

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

   public final void setName(@NotNull String var1) 
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   

   public final int getAge() 
      return this.age;
   

   public final void setAge(int var1) 
      this.age = var1;
   

   public Student(@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 Student copy(@NotNull String name, int age) 
      Intrinsics.checkNotNullParameter(name, "name");
      return new Student(name, age);
   

   // $FF: synthetic method
   public static Student copy$default(Student 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 "Student(name=" + this.name + ", age=" + this.age + ")";
   

   public int hashCode() 
      String var10000 = this.name;
      return (var10000 != null ? var10000.hashCode() : 0) * 31 + this.age;
   

   public boolean equals(@Nullable Object var1) 
      if (this != var1) Kotlin 常用语法篇

kotlin内部类与嵌套类

kotlin内部类与嵌套类

对比Java学Kotlin嵌套类和内部类

对比Java学Kotlin嵌套类和内部类

对比Java学Kotlin嵌套类和内部类