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

Kotlin 为什么JvmStatic方法可以访问和修改状态?,kotlin,static-methods,Kotlin,Static Methods,我假设用@JvmStatic注释的方法将无法访问,更不用说修改类属性了 根据以下情况,情况并非如此。此代码清楚地更新状态,从main-11打印 objectfoo{ 变压杆=5 @JvmStatic 有趣的updateBar(updateVal:Int){ println(“bar=$bar”) bar+=updateVal println(“bar=$bar”) } } 主要内容(){ Foo.updateBar(6) println(“来自main-${Foo.bar}”) } 我也对此感到

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

根据以下情况,情况并非如此。此代码清楚地更新状态,从main-11打印

objectfoo{
变压杆=5
@JvmStatic
有趣的updateBar(updateVal:Int){
println(“bar=$bar”)
bar+=updateVal
println(“bar=$bar”)
}
}
主要内容(){
Foo.updateBar(6)
println(“来自main-${Foo.bar}”)
}

我也对此感到惊讶。事实上,因为
Foo
是一个
对象
,所以
栏实际上是JVM上的一个静态字段。
这就是为什么从静态方法访问它不是问题

类的反编译Java代码如下所示:

公共最终课程Foo{
专用静态整型条;
公共静态最终Foo实例;
公共最终int getBar(){
返回杆;
}
公共最终无效退让(int var1){
bar=var1;
}
@JvmStatic
公共静态最终void updateBar(int updateVal){
字符串var1=“bar=”+bar;
布尔值var2=false;
System.out.println(var1);
bar+=updateVal;
var1=“bar=”+bar;
var2=假;
System.out.println(var1);
}
私家富(){
}
静止的{
Foo var0=新的Foo();
实例=var0;
巴=5;
}
}

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

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

但是
@JvmStatic
/
@JvmField
/
@JvmOverloads
都是为了不改变Kotlin的任何行为而设计的,只改变它暴露于Java的方式。方法内部仍然有一个
this
(指
对象Foo
),就像没有注释时一样。发件人:

如果使用此注释,编译器将在对象的封闭类中生成静态方法,并在对象本身中生成实例方法

命名对象也一样:

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
实例方法显然可以操纵实例状态;而静态方法可以简单地调用实例1并定义为

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

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

Foo
是一个
对象,因此它只有一个实例。
Foo
有状态(
bar
),该状态以“静态”方法更新。无论
Foo
@iluvfugu的实例数多少,这都适用。它不适用“无论Foo的实例数多少”:如果
Foo
是一个类,则无法将该方法标记为
@JvmStatic
,当它是一个对象时,其状态为“静态”-同样,不管它是否标记为
@JvmStatic
@AlexeyRomanov,对不起,我不是指
JvmStatic
或它的适用性。我指的是Kotlin对象具有状态的事实。即使它们被编译成静态Java代码,不管是单实例还是非实例,它们都有状态。如果
bar
字段不是静态的,它可以作为
instance.bar
访问(这就是我所期望的情况)。够了,但我仍然觉得用这种方式阅读而不是显式引用实例很奇怪。我觉得奇怪的是:)我写了另一个答案就够了。JVM注释没有改变Kotlin behaviorOkay这一点很好,谢谢。这让事情变得明朗了一点。