为什么 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 的回答,这不是当前实现的工作方式)。
我假设用 @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 的回答,这不是当前实现的工作方式)。