[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
相关推荐
QING6181 小时前
Kotlin 协程新手指南 —— 协程上下文与调度器
android·kotlin·android jetpack
plainGeekDev2 小时前
HttpURLConnection → OkHttp + Kotlin
android·java·kotlin
QING6183 小时前
Kotlin 协程新手指南 —— 协程基础与挂起函数
android·kotlin·android jetpack
plainGeekDev3 小时前
批量写入 → Room 事务
android·java·kotlin
杉氧4 小时前
Kotlin 协程深度解析①:内核解密——揭秘 suspend 挂起函数的灵魂
android·kotlin
朝星4 小时前
Android开发[11]:启动优化
android·kotlin
JohnnyDeng944 小时前
【Android】Android渲染机制:Choreographer与VSYNC深度解析
android·性能优化·kotlin·jetpack
aidou13144 小时前
Kotlin中实现星级评价选择功能(仅支持整数)
前端·kotlin·自定义view·imageview·ontouchevent·customratingbar
aidou13144 小时前
Kotlin中自定义RadioGroup实现多个RadioButton自动换行
android·开发语言·kotlin·shape·radiobutton·selector·radiogroup
Kapaseker5 小时前
Android 线程发展shi
android·kotlin