kotlin init执行顺序

一 代码

kotlin:



package test.f

class Test1 {
}

class TestInit(s: String, i: Int) {

    var name: String? = null
    var age = 0

    private var a :Int = 1

    init {
        this.name = s
        this.age = i
        println("init代码块: $name, $age")
    }

}




转成java

// Test1.java
package test.f;

import kotlin.Metadata;

@Metadata(
   mv = {2, 0, 0},
   k = 1,
   xi = 48,
   d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002¨\u0006\u0003"},
   d2 = {"Ltest/f/Test1;", "", "()V", "untitled"}
)
public final class Test1 {
}
// TestInit.java
package test.f;

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

@Metadata(
   mv = {2, 0, 0},
   k = 1,
   xi = 48,
   d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\b\n\u0002\b\r\u0018\u00002\u00020\u0001B\u0015\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0005¢\u0006\u0002\u0010\u0006R\u000e\u0010\u0007\u001a\u00020\u0005X\u0082\u000e¢\u0006\u0002\n\u0000R\u001a\u0010\b\u001a\u00020\u0005X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\t\u0010\n\"\u0004\b\u000b\u0010\fR\u001c\u0010\r\u001a\u0004\u0018\u00010\u0003X\u0086\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u000e\u0010\u000f\"\u0004\b\u0010\u0010\u0011¨\u0006\u0012"},
   d2 = {"Ltest/f/TestInit;", "", "s", "", "i", "", "(Ljava/lang/String;I)V", "a", "age", "getAge", "()I", "setAge", "(I)V", "name", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "untitled"}
)
public final class TestInit {
   @Nullable
   private String name;
   private int age;
   private int a;

   public TestInit(@NotNull String s, int i) {
      Intrinsics.checkNotNullParameter(s, "s");
      super();
      this.a = 1;
      this.name = s;
      this.age = i;
      String var3 = "init代码块: " + this.name + ", " + this.age;
      System.out.println(var3);
   }

   @Nullable
   public final String getName() {
      return this.name;
   }

   public final void setName(@Nullable String var1) {
      this.name = var1;
   }

   public final int getAge() {
      return this.age;
   }

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

二 解释说明

在Kotlin中,类的初始化顺序严格按照代码中声明的顺序执行。对于提供的TestInit类,执行顺序如下:

  1. 主构造函数参数处理:首先接收s: Stringi: Int
  2. 属性初始化:按声明顺序依次初始化:
    name: String? = null
    age: Int = 0
    private var a: Int = 1
  3. 执行init:最后运行init中的代码,设置nameage的值,并打印信息。

为什么init块在a之后执行?
因为a的声明和初始化(private var a: Int = 1)出现在init块之前。Kotlin会先处理所有在init块之前声明的属性,再执行init块。这保证了在init块中访问a时,它已经被正确初始化。

关键点
声明顺序决定初始化顺序:属性和init块的执行顺序完全由它们在类体中的位置决定。
init块属于初始化阶段:所有在init块之前的属性会先初始化,确保init块中的逻辑可以依赖这些已初始化的值。

三 总结

根据Kotlin的文档,当创建一个类的实例时,初始化顺序是这样的:
首先,主构造函数中的参数被处理;
接着,类体中声明的属性按照它们在代码中的顺序进行初始化;
然后,init块按照它们在类体中的出现顺序执行。
如果有多个init块,它们会按照顺序依次执行。
最后,次构造函数中的代码执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值