[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
相关推荐
Haha_bj12 小时前
七、Kotlin——扩展(Extensions)
android·kotlin
urkay-12 小时前
Android getDrawingCache 过时废弃
android·java·开发语言·kotlin·iphone·androidx
用户693717500138415 小时前
24.Kotlin 继承:调用超类实现 (super)
android·后端·kotlin
alexhilton18 小时前
借助RemoteCompose开发动态化页面
android·kotlin·android jetpack
QING6181 天前
Jetpack Compose Brush API 简单使用实战 —— 新手指南
android·kotlin·android jetpack
QING6181 天前
Jetpack Compose Brush API 详解 —— 新手指南
android·kotlin·android jetpack
鹿里噜哩1 天前
Spring Authorization Server 打造认证中心(二)自定义数据库表
spring boot·后端·kotlin
用户69371750013842 天前
23.Kotlin 继承:继承的细节:覆盖方法与属性
android·后端·kotlin
Haha_bj2 天前
五、Kotlin——条件控制、循环控制
android·kotlin
Kapaseker2 天前
不卖课,纯干货!Android分层你知多少?
android·kotlin