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
@JvmStaticannotation. 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();
}