I would've assumed that a method annotated with @JvmStatic would be unable to access, let alone modify, a class property.
Based on the following this is not the case. This code clearly updates state, printing From main - 11.
object Foo {
var bar = 5
@JvmStatic
fun updateBar(updateVal : Int) {
println("bar = $bar")
bar += updateVal
println("bar = $bar")
}
}
fun main() {
Foo.updateBar(6)
println("From main - ${Foo.bar}")
}
I was also surprised by this. In fact, because Foo is an object, the field bar is actually a static field on the JVM.
That's why it's not a problem to access it from a static method.
The decompiled Java code of your class is the following:
public final class Foo {
private static int bar;
public static final Foo INSTANCE;
public final int getBar() {
return bar;
}
public final void setBar(int var1) {
bar = var1;
}
@JvmStatic
public static final void updateBar(int updateVal) {
String var1 = "bar = " + bar;
boolean var2 = false;
System.out.println(var1);
bar += updateVal;
var1 = "bar = " + bar;
var2 = false;
System.out.println(var1);
}
private Foo() {
}
static {
Foo var0 = new Foo();
INSTANCE = var0;
bar = 5;
}
}
However, I would avoid doing this. It's unexpected and doesn't really convey the intent.
I assume you wouldn't be surprised without the @JvmStatic annotation; objects are allowed to have mutable state just as classes are.
But @JvmStatic/@JvmField/@JvmOverloads are all designed not to change any behavior from Kotlin's point of view, only the way it's exposed to Java. There is still a this inside the method (referring to the object Foo) just like there would be without the annotation. From the documentation:
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...
Same for named objects:
object Obj { @JvmStatic fun callStatic() {} fun callNonStatic() {} }In Java:
Obj.callStatic(); // works fine Obj.callNonStatic(); // error Obj.INSTANCE.callNonStatic(); // works, a call through the singleton instance Obj.INSTANCE.callStatic(); // works too
The instance method obviously can manipulate the instance state; while the static method can simply call the instance one and be defined as
public static final void updateBar(int updateVal) {
Foo.INSTANCE.updateBar(updateVal);
}
(even if according to @Joffrey's answer this isn't the way the current implementation works).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With