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:
TestKotlin.kt
class TestKotlin {
companion object {
val someString = "hello world"
}
}
Which is then called by Java, like this:
TestJava.java
public class TestJava {
String kotlinStaticString = TestKotlin.Companion.getSomeString();
}
but then, there's this option 2:
TestKotlin.kt
v2
class TestKotlin {
companion object {
@JvmStatic // <-- notice the @JvmStatic annotation
val someString = "hello world"
}
}
And then, call it from Java, like this:
TestJava.java
v2
public class TestJava {
String kotlinStaticString = TestKotlin.getSomeString();
}
So my questions are:
- Are these 2 cases any different, in terms of behavior or memory allocation?
- Is there a preference on which one to use?
- Do both create a pseudo static singleton object, like Java static does?
Thanks!
You place the function in the "companion object".
So the java code like this:
will become
You can then use it from inside Kotlin code as
But from within Java code, you would need to call it as
(Which also works from within Kotlin.)
If you don't like having to specify the
Companion
bit you can either add a@JvmStatic
annotation or name your companion class.From the docs:
Adding the
@JvmStatic
annotation looks like thisand then a will exist as a real Java static function, accessible from both Java and kotlin as
DemoClass.myMethod()
.If it is just disliked by the
Companion
name, then you can also provide an explicit name for the companion object looks like this:which will let you call it from Kotlin in the same way, but from java like
DemoClass.Blah.myMethod()
(which will also work in Kotlin).The behavior of the
@JvmStatic
annotation is explained in detail in the documentation. When reading the documentation, you should assume that it gives you all the important information, and behavior differences that are not mentioned in the documentation do not exist.In this case, the documentation says:
In other words, the effect of the annotation is that it tells the compiler to generate an additional method.
Does the documentation mention that there is any difference in behavior or memory allocation? It does not. Therefore, it's safe to assume that there is none.
Is there a preference on which one to use? Normally, an API is declared in one place and used from multiple places. If you're calling a method from Java, then you should declare it as
@JvmStatic
, because adding the@JvmStatic
annotation in one place will allow you to leave out multiple.Companion
references in multiple places.Do both create a pseudo static singleton object, like Java static does? This question does not make sense, because Java static does not create a "pseudo static singleton object". If you declare a static method in a Java class, and then call this method, no objects will be created.
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, thecompanion
object has to be named, unless@JvmStatic
is applied. It’d look less idiomatic otherwise.Stated in the docs:
Note that it will generate an additional method as stated here:
Let's see an example:
The following class
looks like this on bytecode level, here represented as Java code:
If
@JvmStatic
is being applied tocallMe
method though, the bytecode changes to the following:You can see, correctly documented, the static
callMe
function, as part ofOuter
is generated: