objects-kotlin

Objects in Kotlin: Create safe singletons in one line of code (KAD 27)

Kotlin objects are another element of the language that we Android developers are not familiarized with, because there is nothing like that in Java.

In fact, an object is just a data type with a single implementation. So if we want to find something similar in Java, that would be the Singleton pattern. We’ll compare them in the next section.

Singleton vs object

Singleton in Java isn’t as easy to implement as it sounds. One might think it’s as simple as this:

public class Singleton {

    private Singleton() {
    }

    private static Singleton instance;

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }

        return instance;
    }
}

But this code is dangerous, especially if it’s used in different threads. If two threads access this singleton at a time, two instances of this object could be generated. A safer code would be:

public class Singleton {

    private static Singleton instance = null;

    private Singleton(){
    }

    private synchronized static void createInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
    }

    public static Singleton getInstance() {
        if (instance == null) createInstance();
        return instance;
    }
}

As you can see, you need a few lines to create a valid Singleton.

What would be the equivalent in Kotlin?

object Singleton

You don’t need more. You could use the Show bytecode tool you can find at Tools -> Kotlin, and then use the Decompile option. That way, you can see what’s the implementation that the Kotlin team decided to use for singletons.

I really recommend using that tool when you’re not sure what’s happening behind the scenes.

Object declaration

Declaring an object is as simple as declaring a class.

Let’s declare for example an object that implements a database helper:

object MySQLOpenHandler : SQLiteOpenHelper(App.instance, "MyDB", null, 1) {
    
    override fun onCreate(db: SQLiteDatabase?) {
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
    }

}

As you can see, you just need to use the reserved word object instead of class and the rest is the same. Just take into account that objects can’t have a constructor, as we don’t call any constructors to access to them.

The instance of the object will be created the first time we use it. So there’s a lazy instantiation here: if an object is never used, the instance will never be created.

Companion Object

Every class can implement a companion object, which is an object that is common to all instances of that class. It’d come to be similar to static fields in Java.

An implementation example:

class App : Application() {
    companion object {
        lateinit var instance: App
            private set
    }

    override fun onCreate() {
        super.onCreate()
        instance = this
    }

}

In this case I’m creating a class that extends Application and stores it in the companion object its unique instance.

The lateinit indicates that this property won’t have value from the beginning, but will be assigned before it’s used (otherwise it’ll throw an exception).

The private set is used so that a value can’t be assigned from an external class.

Note: You may think that it’d make a lot of sense for App to be an object instead of a class. And so it is, but due to the way the Android framework instantiate the classes, if you try, you’ll see that the application throws an exception when it’s launched. You’ll need App to be a class, and you can create this little Singleton if you want to access to it.

Object expressions

Objects can also be used to create anonymous class implementations.

An example:

recycler.adapter = object : RecyclerView.Adapter() {
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
    }

    override fun getItemCount(): Int {
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
    }

}

Every time you want to create an inline implementation of an interface, for instance, or extend another class, you’ll use the above notation.

But an object can also represent a class that doesn’t exist. You can create it on the fly:

val newObj = object {
    var x = "a"
    var y = "b"
}

Log.d(tag, "x:${newObj.x}, y:${newObj.y}")

Conclusion

Objects are a new concept for those of us coming from Java 6, but there are many ideas that can be associated with existing ones, so you’ll get fast with them.

If you like what you’ve seen, I encourage you to sign up for my free training, where I’ll tell you everything you need to learn about how to create your own Android Apps in Kotlin from scratch.

Training Boost your Android productivity with Kotlin

25 thoughts on “Objects in Kotlin: Create safe singletons in one line of code (KAD 27)”

  1. Hello! Is this singleton correct and safe?

    class Singleton {

    private object Holder { val INSTANCE = Singleton() }

    companion object {
    val instance: Singleton by lazy { Holder.INSTANCE }
    }
    }

  2. I think in java and multithreaded env the only safe way to instantiate is with “private static Singleton instance = new Singleton();” If you instantiate in the get then that also needs to be syncronized. Your java example uses the double if lock idiom which is broke unless you use the java volatile keyword on the instance.

    Keep up the nice kotlin articles

    1. Honestly I had to look for it to write de article, but that’s another reason why using Kotlin Objects is much easier, you don’t need to look for the right solution . Do you have a link to a well implemented one so that I can update the article?

  3. Gabriele Mariotti

    Just a question about the companion objects.In the official doc you can find: “The name of the companion object can be omitted, in which case the name Companion will be used”. Since you can define only a companion object inside a class what is the sense to assign a name?

    1. There’s being an interesting conversation about this here.

      Honestly don’t have an answer, but my guess is that it’s just for readability issues. If your companion object has a very specific goal, it may make sense to give it a name to refer to it.

      I was also thinking that this might be a vestigial feature of Kotlin supporting several companion objects at some point during EAP. But I was looking and couldn’t find it was the case. Wouldn’t make much sense anyway.

  4. For the Companion object example, suppose I need a getInstance function that needs to be synchronized.

    Is the following code correct? Do I have to add any additional thing?

    class MyApp : Application() {

    companion object {
    lateinit var instance: MyApp
    private set

    }

    override fun onCreate() {
    super.onCreate()
    instance = this
    // Do something

    }

    fun getInstance() : MyApp = instance

    }

  5. That ensures you are always using the same instance, but the other reason for synchronized is thread safety. So we know that two threads will be using the same instance, but are we guarded against one reading a property while the other is writing it?

  6. In java, the easiest way to create singletons is to use enums:

    public enum Singleton {
    INSTANCE;
    }

    That’s it.

  7. Giovanni Viglietta

    I really don’t get the Companion Object example. The way I see it, it’s simply storing the _last_ instance of App that’s been created. But you can instantiate App as many times as you want. So why do you call it a Singleton?! It’s clearly nothing like a Singleton.

    1. There should only be one App object in your App, and it’s the Android framework who creates the instance, not you manually. Were you referring to that, or maybe I missing something?

      1. Giovanni Viglietta

        I didn’t know that part. So what happens if you try to instantiate App twice? The constructor of Application throws an exception? If I understand it, App is actually already a Singleton due to its super-class Application, and regardless of the Companion Object that you added to it. And the point of the Companion Object is just to provide a reference to the unique instance of App to different threads? If that’s the case, then I understand the example, although it’s probably not the best choice for a first example on Companion Objects, due to the weird class Application (whose quirks are not explained in your article), which adds to the confusion. For me, the very first paragraph got the point across: “Every class can implement a companion object, which is an object that is common to all instances of that class. It’d come to be similar to static fields in Java.” This was perfectly clear and gave me a good understanding of Companion Objects. What suddenly made it confusing was the example.

      2. Giovanni Viglietta

        By the way, I saw that your book on Kotlin is regarded by some as the best on the subject. I’m going to buy it, considering the overall quality of your blog.

Comments are closed.