Shayaan Siddiqui

With any language, it comes with it’s own vocabulary. In this article, we will be comparing Kotlin with Java.

In Java, the static keyword to denote methods and properties that belong to an object. It is important to note that this is not to the instance of that object. The keyword is also used to create Singletons, which is a widely used design pattern. A Singleton helps you create a single instance of an object that is shared by other objects.

Kotlin has a different way to approach this design pattern. You can use the keyword object to implement the Singleton pattern.

What is a Singleton?

Singleton is a design pattern which ensures that your class has only one instance while providing a global point of access to the object. This pattern is useful when objects need to be shared between different parts of your app and when resources are not readily available to create them.

Singleton in Java

Let’s assume that we wanted to create a Singleton class in Java. We would write the following code because it would allow us to control how the object was created; therefore we are guaranteed that we only have one instance of the object. Unlike a standard class, in our Singleton, we set the constructor as private and create a publically accessible static reference of the object.

While we write the code, we do not want to create our Singleton at startup since it will be expensive to create. To achieve this, we will need to create a static method which will check to see if the object already exists and return it if it does; however if it doesn’t exist then it will need to call the constructor and return the instance.

If you’re a keen developer, you will certainly notice that the above code isn’t thread-safe. If you’re new to coding, allow me to explain why then I will demonstrate code that would resolve the issue.

At any time one thread can pass this check but be put on hold while another thread creates the singleton. When the first thread resumes inside the if block, it creates another instance.

To address this, we will use double checked locking; if the instance is null, the synchronized keyword creates a lock and a second check ensures that the instance has not yet instantiated and is still null. If it’s null, then we can create a new instance of the Singleton. Most people would think that this is enough but it’s not. The instance needs to be marked with the volatile keyword, which tells the compiler that the variable might be modified asynchronously by concurrently running threads.

All this code is the minimal amount of code you would want whenever you wish to create a Singleton in Java. Due to the complexity of the code, simpler tasks often use enums for creating Singletons in Java most of the time.

Singleton in Kotlin

In Kotlin, static methods or fields aren’t available. So we can’t use the same technique as our Java cousin.

The above code is what would be the result of a code conversion from Java with the help of Android Studio/IntelliJ. All static properties and methods are moved to companion object. The code works but we can make it simpler. We will need to remove the constructor and the companion keyword from object. There are differences between object and companion object, this will be covered at a later point in this post.

If we need to access the count() method, it can be accessed over the Singleton object. object, in Kotlin, is a special class that only has one instance. Therefore if you create a class with the object keyword instead of class, the compiler makes the constructor private, creates a static reference for the object and initializes the reference in a static block.

To understand why the simplified Kotlin code is similar to the Java code, you’ll need to understand how the JVM handles the static blocks. It is called only once when the static field is first accessed and is treated in a similar manner to synchronized blocks, even though they do not have the synchronized keyword. When the Singleton class is being initialized, the JVM locks the synchronized block, therefore making it inaccessible for another thread. When the lock is released, the Singleton instance has already been created so the static block will not execute again. Therefore we are guaranteed a single instance of our Singleton, which fulfills the Singleton contract and the object is both thread-safe and instantiated lazily!

There are some limitations in Kotlin; for example your Singleton can’t accept any parameters because the object declaration has no constructor. Even if you wrote your own constructor, it would be impossible to pass the parameter since the non static parameter passed in the constructor isn’t accessible from the static block.

companion object

companion object is similar to object because it is always declared in a class and the properties can be accessed by the host object. The companion object does not require a name but if it was given a name, the caller can access the members by using the companion object’s name. The name is only given as a convenience to the developer.

In the above code, we have similar companion objects with and without a name. As you can see, any caller can access the count() method on SomeClass; alternatively any caller can access the count() method by using the Counter just like a static member of AnotherClass.

Tech Enthusiast and Software Engineer