Is companion object singleton?

Hello there,
I read from documentation that companion object is singleton, so what is the difference between it and object. also I decompiled the code and I saw that every time I access companion, new instance is created, so how is companion object singleton?

public final class test {
   private static final String st = "string";
   public static final test.Companion Companion = new test.Companion((DefaultConstructorMarker)null);

   @Metadata(
      mv = {1, 1, 16},
      bv = {1, 0, 3},
      k = 1,
      d1 = {"\u0000\u0014\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0002\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0005\u001a\u00020\u0004R\u000e\u0010\u0003\u001a\u00020\u0004X\u0082T¢\u0006\u0002\n\u0000¨\u0006\u0006"},
      d2 = {"Lother/test$Companion;", "", "()V", "st", "", "create", "kotlin"}
   )
   public static final class Companion {
      @NotNull
      public final String create() {
         return "string";
      }

      private Companion() {
      }

      // $FF: synthetic method
      public Companion(DefaultConstructorMarker $constructor_marker) {
         this();
      }
   }
}
  1. The companion object is an object (singleton) that companies (belongs to) a class.
    (this is an other way for implementing static methods in other languages).
    You can put properties/functions inside of it which are the same for every instance:
  • properties can be values that you use inside the class
  • methods. When you pass an instance, or if it creates an instance, it can access private members of that instance

When you make the members of a companion object private, only class instances can access those variables/methods.
When you make them public, you can access them by the class-name.

  1. The constructor is only being called once (when it is stored inside the field Companion) all the other times that field is accessed.

I use them for values that have specific meaning for my class (maxItems, intentParam, etc.)
To make functions like constructors if they need need calculations before they can really construct the class:

class A{
    companion object{
        operator fun invoke(...){
            ...
            return A()
       }
   } 

}

or for DSLs:

class SomeDsl{
    ...
    private fun build() : Some =...
    companion object{
        fun build(
            initialParams :...,
            builder: SomeDsl.()-> Unit
        ) = SomeDsl.also(builder).build()
   }
}

And then you can add it to Some, if it has a companion - object:

fun Some.Companion.build(...)=SomeDsl.build(...)

Spoken about extension - functions, you can kind of add constructors this way to the class to:

operator fun Some.Companion.invoke(...) = Some(...)

Never used it, but as it is just an object, it can implement interfaces.

okay, what about this create function inside the companion, will it create Retrofit instance many times if it is called more than once, or just one instance as the companion object instance?

    companion object {
        private const val BASE_URL = "https://mars.udacity.com/"

        private val moshi: Moshi = Moshi.Builder()
            // to make moshi annotations to work probably with kotlin, we add [KotlinJsonAdapterFactory]
            .add(KotlinJsonAdapterFactory())
            .build()

        fun create(): MarsApiService {
            return Retrofit.Builder()
                .addConverterFactory(MoshiConverterFactory.create(moshi))
                .baseUrl(BASE_URL)
                .build().create(MarsApiService::class.java)
        }
    }

I don’t know about Moshi.

I can tell about the Companion object:
create is just a normal function.
When you call create, its body will execute.

If the class is nested inside class Test:

The variable moshi will be assigned only once: when class Test is loaded (this is probably when you touch it the first time). It doesn’t matter how often you create an instance.

Just to be entirely correct, it does not use a database or something like that, so when you restart the program it creates the singleton again :wink:

I am to tired to really think, but it’s possible that the reflection-part is important to know, or that it’s just pity.

EDIT:
Hmm, it’s just pity…
It’s just telling that if you change the constructor of a companion object to public, you can create multiple types…

1 Like

I just wanted to ensure that the object that returns from create function is created only once. I used a property with lazy initialization and I think it may do the work. thank you :smile:

1 Like

Ah, an lazy value which is created once and belongs to a particular class:

companion object {
    val service by lazy {
         ...
   }
} 

You can even define thread-safety inside lazy

If it doesn’t need to be lazy, assign inside the companion object immediately.

Glad I could help

1 Like

thanks :smile: