[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
相关推荐
zhangphil1 天前
Android Coil3视频封面抽取封面帧存Disk缓存,Kotlin
android·kotlin
QING6181 天前
Media3 ExoPlayer 快速实现背景视频播放(干货)
android·前端·kotlin
安卓开发者1 天前
深入理解Android Kotlin Flow:响应式编程的现代实践
android·kotlin·echarts
FunnySaltyFish1 天前
用cursor写了个基于大模型自动提取并翻译项目字符串的工具
android·vue.js·kotlin
pengyu2 天前
【Kotlin系统化精讲:伍】 | 数据类型之空安全:从防御性编程到类型革命🚀
android·kotlin
彼方卷不动了2 天前
【AI 学习】用 Kotlin 开发一个最基础的 MCP Server 并让它与 Cursor 联动
人工智能·kotlin·mcp
xzkyd outpaper3 天前
Kotlin 协程线程切换机制详解
android·开发语言·kotlin
zhangphil3 天前
Android MediaMetadataRetriever取视频封面,Kotlin(1)
android·kotlin
pengyu3 天前
【Kotlin系统化精讲:肆】 | 数据类型之基本数据类型:代码世界里的砖瓦水泥沙
android·kotlin
Kiri霧4 天前
Kotlin反射
java·开发语言·kotlin