Greatness of Kotlin : Static methods/fields and companion object

For a lot of people coming from Java to Kotlin, the “lack” of the static 
keyword in Kotlin might be disturbing. One easy way to achieve the same kind of functionality is the companion object. 
Let’s see what a companion object really is under the hood!


Companion object

A companion object in Kotlin looks like this:

class MyClass {
companion object {
val myField = "myField"
}
}

As its name indicates this is a singleton (object) linked (companion) to the class.
 If we transpile its code to Java, we get:

public final class MyClass {
@NotNull
private static final String myField = "myField";
public static final MyClass.Companion Companion = new MyClass.Companion((DefaultConstructorMarker)null);

public static final class Companion {
@NotNull
public final String getMyField() {
return MyClass.myField;
}

private Companion() {
}

// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}

We can notice that myField is accessible through the Companion class instance in Java myClass.Companion.getMyField() while we do not need to specify the companion in Kotlin MyClass.myField (but MyClass.Companion.myField remains a valid way to access our field)


Regular object

The companion keyword indicates the bound between itself and the class; the class itself cannot have more than one companion. 
Still, nothing prevents us from having other objects nested in this class:

class MyClass {
object Companion {
val myField = "myField"
}
}

The transpiled Java then is :

public final class MyClass {
public static final class Companion {
@NotNull
private static final String myField = "myField";
public static final MyClass.Companion INSTANCE;

@NotNull
public final String getMyField() { return myField; }

private Companion() {
INSTANCE = (MyClass.Companion)this;
myField = "myField";
}

static {
new MyClass.Companion();
}
}
}

Here we clearly see a singleton definition and everything remaining scoped within our class Companion. Therefore, the only way to access our field is through the Companion object: MyClass.Companion.myField (Kotlin) and MyClass.Companion.INSTANCE.getMyField() (Java)


Conclusion

Through this article, we tried to show that the keyword companion in a Kotlin class is no magic, it simply creates a bridge through delegation between the parent class and the nested object.
Having a companion object rather than a standard Java field enables to have a full object accessible though our class. 
This gives us some powers we would not have had with some simple Java static fields, some of which will be covered in our next post.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.