我以为带有@JvmStatic
注释的方法将无法访问,更不用说修改类属性了。
基于以下情况,并非如此。此代码清楚地更新状态,打印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上的静态字段。这就是为什么从静态方法访问它不是问题。
您的类的反编译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:
如果使用此批注,则编译器将在对象的封闭类中生成静态方法,并在对象本身中生成实例方法...
与命名对象相同:
object Obj { @JvmStatic fun callStatic() {} fun callNonStatic() {} }
在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的回答,这也不是当前实现的工作方式。