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 needApp
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.
Hello! Is this singleton correct and safe?
class Singleton {
private object Holder { val INSTANCE = Singleton() }
companion object {
val instance: Singleton by lazy { Holder.INSTANCE }
}
}
It is because lazy is thread safe. But why don’t you just use an Object here?
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
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?
Check this implementation for a perfect Java singleton:
https://gist.githubusercontent.com/kevalpatel2106/77d9db74fea4027cca24c7473f072c95/raw/c2237247a6f70efb097a5ab067ef2867d10f6c04/SingletonClass.java
Example above explained very detailed:
https://android.jlelse.eu/how-to-make-the-perfect-singleton-de6b951dfdb0
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?
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.
At Companion Object example… Can you just use “lateinit val instance” instead of overriding with private visibilty the setter accesor?
Thanks!
Ups! “instance = this”
lateinit can’t be used with “val,” only with “var”, so the only way to protect the setter is to make it private.
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
}
Why does it need to be synchronized? There’s no way to create two App instances, as you’re just using `this`. I see that code ok.
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?
No, that’s not covered by the default implementation. You will need to implement it by yourself.
You don’t cover one of the widely used singleton use cases that is a singleton that requires passing arguments in its static factory method (constructor) upon creation.
And Kotlin solution to this will not be as elegant as one line of code.
Here it is explained in great detail: https://medium.com/@BladeCoder/kotlin-singletons-with-argument-194ef06edd9e
Exactly, if you need arguments, then it’s not that easy. I remember having read that article, and it was great. Thanks for sharing!
How do you get a context into an object?
You can’t, an object doesn’t have a constructor. You can check this article when some alternatives are explained: https://medium.com/@BladeCoder/kotlin-singletons-with-argument-194ef06edd9e
In java, the easiest way to create singletons is to use enums:
public enum Singleton {
INSTANCE;
}
That’s it.
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.
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?
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.
Sorry, that’s very intrinsic to the Android framework. You never instantiate the App component yourself. I give all these basic Android concepts for granted in all my articles, and especially the Kotlin ones because my learning method shows current Android devs to migrate from Java to Kotlin. You may find more info about the Application class here: https://developer.android.com/reference/android/app/Application
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.
Thanks! Hope you enjoy it.