Kotlin Companion Object
Posted on March 18, 2018 • 3 minutes • 430 words
Table of contents
What is a Companion Object?
When you are new to Kotlin and you are familiar with Java, you may be wondering how you can create static methods and fields in Kotlin. Unlike Java, Kotlin doesn’t have a static keyword. Kotlin has the concept of a companion object.How to create a Companion Object?
You create it inside of a class with the syntax “companion object{}”class Printer{
companion object {
val testString = "1"
@JvmStatic
fun print(message:String){
println(message)
}
}
}
Now all functions and fields inside the companion object are used like they are “static”.
How to call it from Kotlin
To call the functions/fields from a companion object you use the class and call the functions/fields.Printer.print("Hello World")
How to call it from Java
By default you call companion functions/fields like “KotlinClassName”.Companion."MethodName"Printer.Companion.print("Hello");
But Kotlin has the @JvmStatic Annotation.
@JvmStatic
fun print(message:String){
println(message)
}
Functions and fields that are annotated, can be used from Java like they are usual static functions
Printer.print("Hello World")
How does it work on the JVM
You can use Intellij/Android Studio to see the bytecode that the Kotlin Compiler generates. You can find the menu entry under Tools->Kotlin->Show Kotlin BytecodeWhen you click on Decompile you can see what the Java equivalent to your Kotlin class would look like.
@Metadata(
mv = {1, 1, 9},
bv = {1, 0, 2},
k = 1,
d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0003\u0018\u0000 \u00032\u00020\u0001:\u0001\u0003B\u0005¢\u0006\u0002\u0010\u0002¨\u0006\u0004"},
d2 = {"Lstart/Printer;", "", "()V", "Companion", "production sources for module JKCompanionExample"}
)
public final class Printer {
@NotNull
private static final String testString = "1";
public static final Printer.Companion Companion = new Printer.Companion((DefaultConstructorMarker)null);
@JvmStatic
public static final void print(@NotNull String message) {
Companion.print(message);
}
@Metadata(
mv = {1, 1, 9},
bv = {1, 0, 2},
k = 1,
d1 = {"\u0000\u001c\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\u0003\n\u0002\u0010\u0002\n\u0002\b\u0002\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0010\u0010\u0007\u001a\u00020\b2\u0006\u0010\t\u001a\u00020\u0004H\u0007R\u0014\u0010\u0003\u001a\u00020\u0004X\u0086D¢\u0006\b\n\u0000\u001a\u0004\b\u0005\u0010\u0006¨\u0006\n"},
d2 = {"Lstart/Printer$Companion;", "", "()V", "testString", "", "getTestString", "()Ljava/lang/String;", "print", "", "message", "production sources for module JKCompanionExample"}
)
public static final class Companion {
@NotNull
public final String getTestString() {
return Printer.testString;
}
@JvmStatic
public final void print(@NotNull String message) {
Intrinsics.checkParameterIsNotNull(message, "message");
System.out.println(message);
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
As you can see a companion object is compiled to public static final class Companion inside the Printer class.
What else can you do with companion objects?
- Note: A Kotlin class can only have one companion object
- You can give a companion object a name
companion object MyCompanion {} -
Inheritance and Interfaces
A companion object can extend classes and implement interfaces. But you can not extend companion object because they are final classes.