[Kotlin] 类属性是如何实现的

Kotlin 中的类属性是如何实现的

kotlin 中,我们可以定义类属性,那么这些类属性在 class 文件中是如何实现的呢?

结论

在对应的 class 文件中,会为

  1. 作为 val 的类属性生成对应的 field/getter
  2. 作为 var 的类属性生成对应的 field/getter/setter

代码

我们用如下代码来进行分析(请将代码保存为 A.kt)。

kotlin 复制代码
class Human {
  val name = "张无忌";
  var age = 18;
}

fun main(args: Array<String>) {
  val human = Human()
  println("${human.name} 的年龄是 ${human.age}")
}

下方的命令可以编译 A.kt

bash 复制代码
kotlinc A.kt

编译 A.kt 后,我们会看到如下的 class 文件

text 复制代码
AKt.class
Human.class

查看 Human

我们可以用如下的命令查看 Human.class 的内容

bash 复制代码
javap -v -p Human

部分结果展示如下(常量池等部分已经略去)

text 复制代码
{
  private final java.lang.String name;
    descriptor: Ljava/lang/String;
    flags: (0x0012) ACC_PRIVATE, ACC_FINAL
    RuntimeInvisibleAnnotations:
      0: #23()
        org.jetbrains.annotations.NotNull

  private int age;
    descriptor: I
    flags: (0x0002) ACC_PRIVATE

  public Human();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: ldc           #10                 // String 张无忌
         7: putfield      #14                 // Field name:Ljava/lang/String;
        10: aload_0
        11: bipush        18
        13: putfield      #18                 // Field age:I
        16: return
      LineNumberTable:
        line 1: 0
        line 2: 4
        line 3: 10
        line 1: 16
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      17     0  this   LHuman;

  public final java.lang.String getName();
    descriptor: ()Ljava/lang/String;
    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #14                 // Field name:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 2: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LHuman;
    RuntimeInvisibleAnnotations:
      0: #23()
        org.jetbrains.annotations.NotNull

  public final int getAge();
    descriptor: ()I
    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #18                 // Field age:I
         4: ireturn
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LHuman;

  public final void setAge(int);
    descriptor: (I)V
    flags: (0x0011) ACC_PUBLIC, ACC_FINAL
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: iload_1
         2: putfield      #18                 // Field age:I
         5: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   LHuman;
            0       6     1 <set-?>   I
}

基于 javap 命令给出的结果,我们可以反推出对应的 java 源码是这样的(假如源码是 java 的话)⬇️

java 复制代码
// 以下代码是我手动转化的,不保证绝对准确,仅供参考

// 类上有注解,这里略,有兴趣的读者朋友可以自行查看它的具体内容
public final class Human {
  @org.jetbrains.annotations.NotNull
  private final java.lang.String name;
  
  private int age;
  
  public Human() {
    super();
    this.name = "张无忌";
    this.age = 18;
  }
  
  @org.jetbrains.annotations.NotNull
  public final java.lang.String getName() {
    return this.name;
  }
  
  public final int getAge() {
    return this.age;
  }
  
  // 其实 "<set-?>" 这个变量名在 java 中并不合法。我是从 LocalVariableTable 属性看到这个变量名的,在这里我只是如实把它粘贴过来了
  public final void setAge(int <set-?>) {
    this.age = <set-?>;
  }
}

kotlin 源码的 Human 类中,namevalagevar。 在 Human.class 文件中,可以找到

  1. 和作为 valname 对应的 field/getter
  2. 和作为 varage 对应的 field/getter/setter
相关推荐
蹦哒1 小时前
Kotlin 与 Java 语法差异
java·python·kotlin
Kapaseker4 小时前
五分钟搞定 Compose 的打字机效果
android·kotlin
Fate_I_C6 小时前
Android现代开发:Kotlin&Jetpack
android·开发语言·kotlin·android jetpack
XiaoLeisj7 小时前
Android Kotlin 全链路系统化指南:从基础语法、类型系统与面向对象,到函数式编程、集合操作、协程并发与 Flow 响应式数据流实战
android·开发语言·kotlin·协程
RainyJiang16 小时前
谱写Kotlin协程面试进行曲-进阶篇(第二乐章)
面试·kotlin·android jetpack
星霜笔记1 天前
GitMob — 手机端 GitHub 管理工具
android·kotlin·github·android jetpack
android_cai_niao1 天前
OkHttp 使用教程:从入门到精通(Kotlin)
okhttp·kotlin
Yang-Never2 天前
OpenGL ES ->YUV图像基础知识
android·java·开发语言·kotlin·android studio
idealzouhu2 天前
【Kotlin】 数据流完全指南:冷流、热流与 Android 实战
android·开发语言·kotlin
常利兵2 天前
Android 字体字重设置:从XML到Kotlin的奇妙之旅
android·xml·kotlin