kotlin代码初始化顺序

kotlin的代码初始化顺序其实我们DeCompile一下就可以看的明明白白了,先来看两个类,子类Sheep和父类Animal,找个地方初始化Sheep即可:

open class Animal(name: String) {
    open var name: String = "I'm a Animal"
        set(value) {
            field = value
        }
        get() = field

    init {
        this.name = "My Name is Animal from init block!"
        init()
    }

    open fun init() {
        name = "My Name is Animal from init function!"
    }

}
class Sheep : Animal("Sheep") {
    override var name = "I'm a Sheep"
        set(value) {
            field = value
        }
        get() = field

    init {
        this.name = name
    }

    override fun init() {
        super.init()
        this.name = "My Name is Sheep from init function!"
    }
}

最后上一个Decompile kotlin的文件看一下应该对执行顺序有所了解了。

@Metadata(
   mv = {1, 1, 15},
   bv = {1, 0, 3},
   k = 1,
   d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0006\n\u0002\u0010\u0002\n\u0000\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\b\u0010\n\u001a\u00020\u000bH\u0016R&\u0010\u0005\u001a\u00020\u00042\u0006\u0010\u0003\u001a\u00020\u00048V@VX\u0096\u000e¢\u0006\u000e\n\u0000\u001a\u0004\b\u0006\u0010\u0007\"\u0004\b\b\u0010\t¨\u0006\f"},
   d2 = {"Lcom/example/lw/grouphelper/Sheep;", "Lcom/example/lw/grouphelper/Animal;", "()V", "value", "", "name", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "init", "", "app_debug"}
)
public final class Sheep extends Animal {
   @NotNull
   private String name = "I'm a Sheep";

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

   public void setName(@NotNull String value) {
      Intrinsics.checkParameterIsNotNull(value, "value");
      this.name = value;
   }

   public void init() {
      super.init();
      this.setName("My Name is Sheep from init function!");
      Log.e("Sheep", this.getName());
   }

   public Sheep() {
      super("Sheep");
      this.setName(this.getName());
      Log.e("Sheep", this.getName());
   }
}
  • 1.首先是父类的变量name被赋值,注意:赋值的状态是Animal.name,而不是name或者this.name,并且在Debug状态下,断点不会停在赋值的位置,我也不知道原因在哪里。
  • 2.接着是父类Animalinit{}初始化代码块。
  • 3.当name被赋值的时候,因为变量的继承关系,调用的是子类里nameset方法。
  • 4.Sheepinit()函数。
  • 5.Animalinit()函数。
  • 6.Sheepnameset函数。
  • 7.最后是Sheepinit{}

总结
1.父类变量的赋值操作是最先被调用的,像Animal.name,在initializer block之前已经有值了:

屏幕快照 2019-07-09 下午9.48.05.png

2.子类的init{}总是最后被调用。
3.因为变量的继承关系,子类中重写的变量的赋值总是调用子类相应变量的set方法,而不是父类的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。