---
title: Companion Objects Are Real Objects Too
teaser: Why companion objects in Kotlin should not be used as a replacement for Java's
  static constant.
tags: kotlin,android
author: Amanda Hill
published_on: 2017-02-06
---

For as long as there have been Android devices, there have been Android
developers programming in Java. Or at least, that was the case until 2011 when
[Jetbrains announced](https://blog.jetbrains.com/kotlin/2011/07/hello-world-2/)
they were developing a new statically typed programming language for the JVM.
And if it's good enough for the JVM then it's good enough for Android!

But why build a new language when Java is so dandy?

> "[We] believe that the community can benefit from a new statically typed
> JVM-targeted language free of the legacy trouble and having the features so
> desperately wanted by the developers."

While Kotlin does make good on its promise to offer Android developers a modern
language, it is not all sunshine and roses. Kotlin giveth, and it also taketh
away. One example is static constants. In Java, classes can have static
constants - fields that are only created once per class (as opposed to
once per object), cannot be changed (without recompiling), and can be accessed
without an instance of their containing class. Static constants are a great tool
for developers as they allow us to share the same variable (both in value and in
memory location) across all instances of a given class. While the memory storage
is a nice bonus, the real advantage is in their ability to encode meaning into
an otherwise random variable. Consider the following:

```java
private static final int MAX_ALPHA = 255;
```

Because the static constant we are defining is a primitive type, the compiler
will replace our constant name everywhere with its value, in this case `255`, at
compile time. So there is absolutely no reason for us to not just write `255`
everywhere we use that constant. Well, no reason, except that 255 on it's own is
a [magic number](https://en.m.wikipedia.org/wiki/Magic_number_(programming))
which  someone else, might, very reasonably, not know happens to be the maximum
value representable by an eight-digit binary number and therefore represents the
maximum value that can be assigned to elements in the 24-bit RGBA color model,
since each color channel is allotted eight bits. But I digress.

All of that (totally) unnecessary (but hopefully informative) mathematic malarky
was to make the point that static constants are valuable and can be very helpful
in making code more readable.

But why does any of that matter in terms of Kotlin? Well in Kotlin, we don't
have static constants anymore.

The official Kotlin documentation recommends the following alternatives:

> If you need to write a function that can be called without having a class
> instance ... you can write it as a member of an object declaration inside that
> class.

> Even more specifically, if you declare a companion object inside your class,
> you'll be able to call its members with the same syntax as calling static
> methods in Java/C#, using only the class name as a qualifier.

If you read that and thought, "companion objects are for me! They'll make my
Kotlin code can look just like my Java code and, just as Bob Marley predicted,
'every little thing gonna be alright'!" Then you are just like me. And sadly,
just like me, you would be wrong. Every little thing not gonna be alright. While
companion objects do offer us the same syntax as our dear Java static constants,
they are _not_ the same thing.

Consider how our earlier static constant would look in Kotlin:

```kotlin
companion object {
  private val MAX_ALPHA: Int = 255
}
```

Looks pretty similar right?. Well, as the title of this blog post suggests,
companion objects are objects too. Which means that to get at that `MAX_ALPHA`
we would actually have to create an object first, then access it's member
variable. And object creation is expensive. And let me tell you, that integer is
not worth the cost. How do I know? Because my Android [trace
profile](https://developer.android.com/studio/profile/traceview.html) told me of
course!

Don't believe me? Let's take a look at some profiles. Consider a custom view
that uses our `MAX_ALPHA` value on each `onDraw` call.

Here's what the profile looks if we use a companion object:

![](https://images.thoughtbot.com/blog-vellum-image-uploads/dsaSudbySuaVhYvcJQWl_FUt6nPdSMGSG9Wx19tR7.png)

I have highlighted the row fetching the `MAX_ALPHA` variable from the companion
object class.

Now here is what the trace looks like if we just place the `MAX_ALPHA` as just a
class variables:

![](https://images.thoughtbot.com/blog-vellum-image-uploads/p6Odw53lRlKl4CV1hfeX_Rci7iGAOQu65EzZJfhP1.png)

You will notice that total CPU Time % for the same `drawDiagonalLines` method
went from 18.7% with a companion object, to 11.1% without it! Do you believe me
now?

For the purposes of this exmaple, replacing a companion object with a class
variable was an acceptable solution, but if that won't work for you, and you
need a constant with a broader scope, you can use package-level functions.

Regardless of what soltuion you go with, as long as you remember that companion
objects are objects too, and not the same as Java's static constants, then,
maybe, just maybe, ["every little thing is gonna be
alright"](https://www.youtube.com/watch?v=mACqcZZwG0k)
