最近开始学习Kotlin。在 Kotlin 中声明 main 函数时,我注意到一个有趣的行为。即使在对象类中,它也使用 @JvmStatic 注释。我环顾四周,没有找到相关的帖子。
object Main {
@JvmStatic
fun main(args: Array<String>) {
println("Hello World")
}
}
为什么 Kotlin 中的 main 函数需要 @JvmStatic 注解?
来自 Java 和 Scala 的背景,这似乎是多余和不必要的,所以我很好奇 Kotlin 采用这种约定的背景和决策是什么。
@JvmStatic
声明为顶级函数,则
main
是 not 必需的。也就是说,如果您的整个 Kotlin 源文件是:
fun main(args: Array<String>) {
println("Hello World")
}
在这种情况下您不需要
@JvmStatic
- 所有顶级函数都被转换为 Java 中的静态方法,默认情况下在一个名为 XXXKt
的类中,其中 XXX
是您的 Kotlin 文件名。
请注意,对于 Kotlin 中的无参数顶层
main
s,编译器实际上生成一个适当的 Java main
接受 String[] args
,并委托给您的 Kotlin 函数。
// the Kotlin main gets converted to something like this...
public static void main$1() {
// your kotlin code here...
}
// A proper Java main generated by Kotlin
public static void main(String[] args) {
main$1();
}
当您将 @JvmStatic
方法放在
main
中时,您 do需要
object
,因为 object
s 在 Java 中被转换为单例类。 object
中的所有成员默认都是非静态的。
object MyObject {
fun main(args: Array<String>) {
}
}
被翻译成这样:
public final class MyObject {
private MyObject() {}
public static final MyObject INSTANCE = new MyObject();
public void main(String[] args) { }
}
当你在 Kotlin 中执行
MyObject.main(...)
时,它实际上是 Java 中的 MyObject.INSTANCE.main(...)
。显然,这样的main
方法不能作为Java程序的入口点,因为它不是静态的。
Kotlin 没有直接等同于 Java 静态方法。最接近它的是顶级函数(不属于任何类的函数)。为了在 Java 中调用它们,它们会自动编译为生成的类中的 Java 静态方法,该类以附加“Kt”的文件命名。
Kotlin
object
s 在 Java 中没有直接的等价物。 object
是类的实际实例。它的功能只是常规的非静态方法。可以通过 Java 中生成的 INSTANCE
静态字段访问 Kotlin 对象。这只是返回 Kotlin 对象的类实例。通过它,你可以访问它的方法。
@JvmStatic
告诉编译器将函数编译为静态。这不是自动完成的原因是它对 Kotlin 中通常不存在的功能施加了一系列限制,因此有必要要求选择加入。例如,它不能引用或调用特定于类实例的任何东西,例如在其超类中定义的函数/属性,也不能覆盖任何东西。