I\'m trying to understand the difference between using/not using @JvmStatic, and when I should use either one.
So, with Kotlin and Java, I can do this:
In Kotlin, the companion
object can be us used to imitate static behaviour, calls look like static calls in Java, the “Companion“
isn’t part of if. If used in Java though, the companion
object has to be named, unless @JvmStatic
is applied. It’d look less idiomatic otherwise.
TestKotlin.getSomeString() //this should be preferred whenever possible
Stated in the docs:
Companion Objects
An object declaration inside a class can be marked with the companion keyword:
class MyClass { companion object Factory { fun create(): MyClass = MyClass() } }
Members of the companion object can be called by using simply the class name as the qualifier:
val instance = MyClass.create()
...
However, on the JVM you can have members of companion objects generated as real static methods and fields, if you use the
@JvmStatic
annotation. See the Java interoperability section for more details.
Note that it will generate an additional method as stated here:
If you use this annotation, the compiler will generate both a static method in the enclosing class of the object and an instance method in the object itself.
Let's see an example:
The following class
class Outer {
companion object {
fun callMe() = ""
}
}
looks like this on bytecode level, here represented as Java code:
@Metadata(...)
public final class Outer {
public static final Outer.Companion Companion = new Outer.Companion((DefaultConstructorMarker)null);
@Metadata(...)
public static final class Companion {
@NotNull
public final String callMe() {
return "";
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
If @JvmStatic
is being applied to callMe
method though, the bytecode changes to the following:
@Metadata(...)
public final class Outer {
public static final Outer.Companion Companion = new Outer.Companion((DefaultConstructorMarker)null);
@JvmStatic
@NotNull
public static final String callMe() {
return Companion.callMe();
}
@Metadata(...)
public static final class Companion {
@JvmStatic
@NotNull
public final String callMe() {
return "";
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
You can see, correctly documented, the static callMe
function, as part of Outer
is generated:
@JvmStatic
@NotNull
public static final String callMe() {
return Companion.callMe();
}