Singleton class in Kotlin with init

Viewed 732

I just to wish clarify some methodology using singletons in Kotlin.

I have this 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")
 }
}

And this test functions:

1. TestClass.instance.runSync1()
2. TestClass.runSync2()
3. TestClass().runSync1()
  1. When calling function 1 twice, init inside companion object will be called once. So only one instance of TestClass is created and run runSync1() twice, correct?
  2. When calling function 2 twice, init inside companion object will be called once. So only one instance of TestClass is created and run runSync2() twice, correct? So what is the difference between 1 and 2?
  3. When calling function 2 twice, 2 instances of TestClass crated, 2 init inside class will run and 2 runSync1 will run independently?

Can you please provide more clarification and correct the wrong parts?

1 Answers

When understanding the companion objects one thing to remember is that

A companion object is initialized when the corresponding class is loaded (resolved) that matches the semantics of a Java static initializer.

So the init block inside the companion object will be executed only once, when the TestClass is being loaded, same goes with the property named instance, it will be assigned an object of TestClass only once at class load time.

To better understand this you can look at your code converted to java, which will look something like

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();
        }
    }
}
Related