Kotlin 中带有 init 的单例 class

Singleton class in Kotlin with init

我只是想澄清一些在 Kotlin 中使用单例的方法。

我有这个class:

class TestClass {

companion object {
    val instance = TestClass()

    fun runSync2() {
        Log.d("TAG", "Running sync2")
    }
    
    init {
        Log.d("TAG", "Init companion")
    }
}

init {
    Log.d("TAG", "Init class")
}

fun runSync1() {
    Log.d("TAG", "Running sync1")
 }
}

这个测试函数:

1. TestClass.instance.runSync1()
2. TestClass.runSync2()
3. TestClass().runSync1()
  1. 调用函数1两次时,伴随对象内部的init会被调用一次。所以只创建了一个 TestClass 实例并且 运行 运行Sync1() 两次,对吗?
  2. 调用函数2两次时,伴随对象内部的init会被调用一次。所以只创建了一个 TestClass 实例并且 运行 运行Sync2() 两次,对吗?那么1和2有什么区别呢?
  3. 当两次调用函数 2 时,2 个 TestClass 实例被创建,class 中的 2 个初始化将 运行 和 2 个 运行Sync1 将独立地 运行?

能否请您提供更多说明并更正错误部分?

理解同伴对象时要记住的一件事是

当加载(解析)与 Java 静态初始化程序的语义匹配的相应 class 时,伴随对象被初始化。

因此 companion 对象中的 init 块将只执行一次,当 TestClass 被加载时,与 属性 命名为 instance,它只会在 class 加载时被分配一次 TestClass 的对象。

为了更好地理解这一点,您可以查看转换为 java 的代码,它类似于

public final class TestClass {

    // Property of companion object and the init block are now part of TestClass
    private static final TestClass instance = new TestClass();

    static {
       Log.d("TAG", "Init companion");
    }

    public static final TestClass.Companion Companion = new TestClass.Companion((DefaultConstructorMarker)null);

    public final void runSync1() {
        Log.d("TAG", "Running sync1");
    }

    public TestClass() {
        Log.d("TAG", "Init class");
    }


    public static final class Companion {
        public final TestClass getInstance() {
            return TestClass.instance;
        }

        public final void runSync2() {
            Log.d("TAG", "Running sync2");
        }

        private Companion() { }

        public Companion(DefaultConstructorMarker $constructor_marker) {
            this();
        }
    }
}