为什么 JvmStatic 方法可以访问和修改状态?

Why is it possible for a JvmStatic method to access and modify state?

我假设用 @JvmStatic 注释的方法将无法访问,更不用说修改 class 属性.

基于以下事实并非如此。此代码清楚地更新状态,打印 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}")
}

我对此也感到意外。事实上,因为Foo是一个object,字段bar实际上是JVM上的一个静态字段。 这就是为什么从静态方法访问它不是问题。

你的class的反编译Java代码如下:

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;
   }
}

但是,我会避免这样做。这是出乎意料的,并没有真正传达意图。

我想如果没有 @JvmStatic 注释,您不会感到惊讶;允许对象具有可变状态,就像 类 一样。

但是 @JvmStatic/@JvmField/@JvmOverloads 都被设计为 从 Kotlin 的角度来看不改变任何行为,只是方式它暴露于 Java。方法里面还有一个this(指的是object Foo),就像没有注解一样。来自 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

实例方法显然可以操作实例状态;而静态方法可以简单地调用实例一并定义为

public static final void updateBar(int updateVal) {
    Foo.INSTANCE.updateBar(updateVal);
}

(即使根据@Joffrey 的回答,这不是当前实现的工作方式)。