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