Language design

“Static constants” in Kotlin

Kotlin is designed so that there’s no such thing as a “static member” in a class. If you have a function in a class, it can only be called on instances of this class. If you need something that is not attached to an instance of any class, you define it in a package, outside any class (we call it package-level functions):

package foo

fun bar() {}

But sometimes you need static constants in your class: for example, to comply with requirements of some framework or to use serialization. How do you do this in Kotlin? There are two things in Kotlin that resemble Java’s statics: aforementioned package-level functions and class objects. I’ll explain briefly what class objects are and then proceed to static constants.

Class Objects

A class (not inner and not local) or trait may declare at most one class object associated with it. For example:

class Foo {
  class object {
    val bar = 1
  }

  val baz = 2
}

Here we have a class, Foo, that declares a class object, which in turn has a member property bar. This means that we can call bar directly on a class name (just like in Java):

println(Foo.bar)

Note that we can not call bar on an instance of Foo:

val foo = Foo()
println(foo.bar) // compilation error

That’s because bar is not a member of Foo, only of its class object. Class object is a separate entity associated with the class, and does not share members with its instances. Neither can we call baz on the class name:

prinltn(Foo.baz) // error

This is because baz is a member of Foo, not of its class object, so you can only call baz on instances of Foo.

Now, let’s look at how class objects work. First, there’s a separate JVM class generated for a class object, and bar is a member of that class. If you access class objects from Java, you have to say something like this:

/* Java */
Foo.object$.getBar()

Class object is an instance stored in a static field inside the class it is defined in, and its properties are accessed with getters/setters.

Static Constants

A property in a class object works as well as a static field (and even better), but only in Kotlin. As we saw above, for Java it looks different, and this may cause problems if some framework or convention (in Java) requires you to have a real static field.

Disclaimer: in Kotlin M5.3 there’s no way to have a static field in your class. It was implemented very recently, so you have it only in the latest nightly build.

When you define a public or internal property in your class object, and do not specify custom getter, nor setter, Kotlin automatically stores it directly in the enclosing class, so that in Java you can say

System.out.println(Foo.bar);

There’s no difference for your Kotlin code: everything works as it should. Even in Java the old-fashioned Foo.object$.getBar(), but now you can also have real static constants in your class.

Enjoy.

image description