@JvmStatic properties

Let's examine the impact of @JvmStatic on a companion object property. Let's start out with the following snippet, which defines a companion object on a Widget class:

class Widget {
companion object {
val foo = "foo"
}
}

The foo property we defined earlier can be used from Java, as shown in the following code:

// Main.java
public class
Main {
public static void main(String[] args) {
Widget.Companion.getFoo();
}
}

There is a possible issue with this code, though. The foo property is an instance on an actual class. This means that an instance of the companion object has to be instantiated to access foo

public final class Widget {
@NotNull
private static final String foo = "foo";
...
public static final class Companion {
@NotNull
public final String getFoo() {

return Widget.foo;
}
...
}
}

If we would like to access foo with a true static method on the Widget class, we can add @JvmStatic to the property definition on the companion object:

class Widget {
companion object {
@JvmStatic val foo = "foo"
}
}

Once the annotation has been added, the compiler will generate a true JVM static getter for foo, as shown in the following code:

public final class Widget {
@NotNull
private static final String foo = "foo";
...

@NotNull
public static final String getFoo() {

Widget.Companion var10000 = Companion;
return foo;
}

public static final class Companion {
...
}
}

With this generated getter available, we can access foo without an instance of the companion object:

// Main.java
public class Main {
public static void main(String[] args) {
...
Widget.getFoo();
}
}

Not only is this new syntax less verbose and more Java idiomatic, but it's more efficient as well as we don't have to generate a new instance of a class to access the constant, foo. This usage of @JvmStatic can be applied to more than just properties. In the next section, we'll look at using @JvmStatic with companion object methods.