如何为 Java 创建 Kotlin 静态变量和函数?
How do you make Kotlin static variables and functions for Java?
自从 Google 使 Kotlin 成为 Android 的第一个 class 语言以来,关于如何在 Kotlin 中执行某些事情的问题越来越多,"Java-esque"风格。最常见的是如何在 Kotlin 中制作 static
变量。那么如何制作 Kotlin static
变量和函数呢?
你不能。好吧,至少在 纯 Kotlin 项目中是这样。
Kotlin 没有 static
的概念。 static
在 Kotlin-Java 项目中的工作方式是通过在 Kotlin 类 上使用注释来告诉 JVM 所需的 variable/function 应该作为 static
到 Java 类.
以下是 Kotlin-Java static
互操作的示例指南(答案最初发布于 ):
Scenario 1: Creating a static method in Kotlin for Java
Kotlin
@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java
package com.frybits
class KotlinClass {
companion object {
//This annotation tells Java classes to treat this method as if it was a static to [KotlinClass]
@JvmStatic
fun foo(): Int = 1
//Without it, you would have to use [KotlinClass.Companion.bar()] to use this method.
fun bar(): Int = 2
}
}
Java
package com.frybits;
class JavaClass {
void someFunction() {
println(KotlinClass.foo()); //Prints "1"
println(KotlinClass.Companion.bar()); //Prints "2". This is the only way to use [bar()] in Java.
println(KotlinClass.Companion.foo()); //To show that [Companion] is still the holder of the function [foo()]
}
//Because I'm way to lazy to keep typing [System.out], but I still want this to be compilable.
void println(Object o) {
System.out.println(o);
}
}
这个 提供了比这个更深入的内容,绝对应该作为这个场景的参考。
下一个场景处理在 Kotlin 中创建静态字段,这样 Java 就不必在不需要静态函数的情况下继续调用 KotlinClass.foo()
。
Scenario 2: Creating a static variable in Kotlin for Java
Kotlin
@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java
package com.frybits
class KotlinClass {
companion object {
//This annotation tells Kotlin to not generate the getter/setter functions in Java. Instead, this variable should be accessed directly
//Also, this is similar to [@JvmStatic], in which it tells Java to treat this as a static variable to [KotlinClass].
@JvmField
var foo: Int = 1
//If you want something akin to [final static], and the value is a primitive or a String, you can use the keyword [const] instead
//No annotation is needed to make this a field of [KotlinClass]. If the declaration is a non-primitive/non-String, use @JvmField instead
const val dog: Int = 1
//This will be treated as a member of the [Companion] object only. It generates the getter/setters for it.
var bar: Int = 2
//We can still use [@JvmStatic] for 'var' variables, but it generates getter/setters as functions of KotlinClass
//If we use 'val' instead, it only generates a getter function
@JvmStatic
var cat: Int = 9
}
}
Java
package com.frybits;
class JavaClass {
void someFunction() {
//Example using @JvmField
println(KotlinClass.foo); //Prints "1"
KotlinClass.foo = 3;
//Example using 'const val'
println(KotlinClass.dog); //Prints "1". Notice the lack of a getter function
//Example of not using either @JvmField, @JvmStatic, or 'const val'
println(KotlinClass.Companion.getBar()); //Prints "2"
KotlinClass.Companion.setBar(3); //The setter for [bar]
//Example of using @JvmStatic instead of @JvmField
println(KotlinClass.getCat());
KotlinClass.setCat(0);
}
void println(Object o) {
System.out.println(o);
}
}
Kotlin 的一大特色是您可以创建顶级函数和变量。这使得创建常量字段和函数的“无类”列表变得更好,它们又可以用作 static
functions/fields in Java.
Scenario 3: Accessing top level fields and functions in Kotlin from Java
Kotlin
//In this example, the file name is "KSample.kt". If this annotation wasn't provided, all functions and fields would have to accessed
//using the name [KSampleKt.foo()] to utilize them in Java. Make life easier for yourself, and name this something more simple
@file:JvmName("KotlinUtils")
package com.frybits
//This can be called from Java as [KotlinUtils.TAG]. This is a final static variable
const val TAG = "You're it!"
//Since this is a top level variable and not part of a companion object, there's no need to annotate this as "static" to access in Java.
//However, this can only be utilized using getter/setter functions
var foo = 1
//This lets us use direct access now
@JvmField
var bar = 2
//Since this is calculated at runtime, it can't be a constant, but it is still a final static variable. Can't use "const" here.
val GENERATED_VAL:Long = "123".toLong()
//Again, no need for @JvmStatic, since this is not part of a companion object
fun doSomethingAwesome() {
println("Everything is awesome!")
}
Java
package com.frybits;
class JavaClass {
void someFunction() {
println(KotlinUtils.TAG); //Example of printing [TAG]
//Example of not using @JvmField.
println(KotlinUtils.getFoo()); //Prints "1"
KotlinUtils.setFoo(3);
//Example using @JvmField
println(KotlinUtils.bar); //Prints "2". Notice the lack of a getter function
KotlinUtils.bar = 3;
//Since this is a top level variable, no need for annotations to use this
//But it looks awkward without the @JvmField
println(KotlinUtils.getGENERATED_VAL());
//This is how accessing a top level function looks like
KotlinUtils.doSomethingAwesome();
}
void println(Object o) {
System.out.println(o);
}
}
另一个可以在 Java 中用作“静态”字段的值得注意的提及是 Kotlin object
类。这些是零参数单例类,在第一次使用时懒惰地实例化。有关它们的更多信息,请参见此处:https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
但是,要访问单例,会创建一个特殊的 INSTANCE
对象,处理起来和 Companion
一样麻烦。以下是如何使用注释使其在 Java:
中具有干净的 static
感觉
Scenario 4: Using object
classes
Kotlin
// There is no more need for the @file:JvmName() annotation. The object class below already handles the proper naming.
//This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java
package com.frybits
object KotlinClass { //No need for the 'class' keyword here.
//Direct access to this variable
const val foo: Int = 1
//Tells Java this can be accessed directly from [KotlinClass]
@JvmStatic
var cat: Int = 9
//Just a function that returns the class name
@JvmStatic
fun getCustomClassName(): String = this::class.java.simpleName + "boo!"
//Getter/Setter access to this variable, but isn't accessible directly from [KotlinClass]
var bar: Int = 2
fun someOtherFunction() = "What is 'INSTANCE'?"
}
Java
package com.frybits;
class JavaClass {
void someFunction() {
println(KotlinClass.foo); //Direct read of [foo] in [KotlinClass] singleton
println(KotlinClass.getCat()); //Getter of [cat]
KotlinClass.setCat(0); //Setter of [cat]
println(KotlinClass.getCustomClassName()); //Example of using a function of this 'object' class
println(KotlinClass.INSTANCE.getBar()); //This is what the singleton would look like without using annotations
KotlinClass.INSTANCE.setBar(23);
println(KotlinClass.INSTANCE.someOtherFunction()); //Accessing a function in the object class without using annotations
}
void println(Object o) {
System.out.println(o);
}
}
自从 Google 使 Kotlin 成为 Android 的第一个 class 语言以来,关于如何在 Kotlin 中执行某些事情的问题越来越多,"Java-esque"风格。最常见的是如何在 Kotlin 中制作 static
变量。那么如何制作 Kotlin static
变量和函数呢?
你不能。好吧,至少在 纯 Kotlin 项目中是这样。
Kotlin 没有 static
的概念。 static
在 Kotlin-Java 项目中的工作方式是通过在 Kotlin 类 上使用注释来告诉 JVM 所需的 variable/function 应该作为 static
到 Java 类.
以下是 Kotlin-Java static
互操作的示例指南(答案最初发布于
Scenario 1: Creating a static method in Kotlin for Java
Kotlin
@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java package com.frybits class KotlinClass { companion object { //This annotation tells Java classes to treat this method as if it was a static to [KotlinClass] @JvmStatic fun foo(): Int = 1 //Without it, you would have to use [KotlinClass.Companion.bar()] to use this method. fun bar(): Int = 2 } }
Java
package com.frybits; class JavaClass { void someFunction() { println(KotlinClass.foo()); //Prints "1" println(KotlinClass.Companion.bar()); //Prints "2". This is the only way to use [bar()] in Java. println(KotlinClass.Companion.foo()); //To show that [Companion] is still the holder of the function [foo()] } //Because I'm way to lazy to keep typing [System.out], but I still want this to be compilable. void println(Object o) { System.out.println(o); } }
这个
下一个场景处理在 Kotlin 中创建静态字段,这样 Java 就不必在不需要静态函数的情况下继续调用 KotlinClass.foo()
。
Scenario 2: Creating a static variable in Kotlin for Java
Kotlin
@file:JvmName("KotlinClass") //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java package com.frybits class KotlinClass { companion object { //This annotation tells Kotlin to not generate the getter/setter functions in Java. Instead, this variable should be accessed directly //Also, this is similar to [@JvmStatic], in which it tells Java to treat this as a static variable to [KotlinClass]. @JvmField var foo: Int = 1 //If you want something akin to [final static], and the value is a primitive or a String, you can use the keyword [const] instead //No annotation is needed to make this a field of [KotlinClass]. If the declaration is a non-primitive/non-String, use @JvmField instead const val dog: Int = 1 //This will be treated as a member of the [Companion] object only. It generates the getter/setters for it. var bar: Int = 2 //We can still use [@JvmStatic] for 'var' variables, but it generates getter/setters as functions of KotlinClass //If we use 'val' instead, it only generates a getter function @JvmStatic var cat: Int = 9 } }
Java
package com.frybits; class JavaClass { void someFunction() { //Example using @JvmField println(KotlinClass.foo); //Prints "1" KotlinClass.foo = 3; //Example using 'const val' println(KotlinClass.dog); //Prints "1". Notice the lack of a getter function //Example of not using either @JvmField, @JvmStatic, or 'const val' println(KotlinClass.Companion.getBar()); //Prints "2" KotlinClass.Companion.setBar(3); //The setter for [bar] //Example of using @JvmStatic instead of @JvmField println(KotlinClass.getCat()); KotlinClass.setCat(0); } void println(Object o) { System.out.println(o); } }
Kotlin 的一大特色是您可以创建顶级函数和变量。这使得创建常量字段和函数的“无类”列表变得更好,它们又可以用作 static
functions/fields in Java.
Scenario 3: Accessing top level fields and functions in Kotlin from Java
Kotlin
//In this example, the file name is "KSample.kt". If this annotation wasn't provided, all functions and fields would have to accessed //using the name [KSampleKt.foo()] to utilize them in Java. Make life easier for yourself, and name this something more simple @file:JvmName("KotlinUtils") package com.frybits //This can be called from Java as [KotlinUtils.TAG]. This is a final static variable const val TAG = "You're it!" //Since this is a top level variable and not part of a companion object, there's no need to annotate this as "static" to access in Java. //However, this can only be utilized using getter/setter functions var foo = 1 //This lets us use direct access now @JvmField var bar = 2 //Since this is calculated at runtime, it can't be a constant, but it is still a final static variable. Can't use "const" here. val GENERATED_VAL:Long = "123".toLong() //Again, no need for @JvmStatic, since this is not part of a companion object fun doSomethingAwesome() { println("Everything is awesome!") }
Java
package com.frybits; class JavaClass { void someFunction() { println(KotlinUtils.TAG); //Example of printing [TAG] //Example of not using @JvmField. println(KotlinUtils.getFoo()); //Prints "1" KotlinUtils.setFoo(3); //Example using @JvmField println(KotlinUtils.bar); //Prints "2". Notice the lack of a getter function KotlinUtils.bar = 3; //Since this is a top level variable, no need for annotations to use this //But it looks awkward without the @JvmField println(KotlinUtils.getGENERATED_VAL()); //This is how accessing a top level function looks like KotlinUtils.doSomethingAwesome(); } void println(Object o) { System.out.println(o); } }
另一个可以在 Java 中用作“静态”字段的值得注意的提及是 Kotlin object
类。这些是零参数单例类,在第一次使用时懒惰地实例化。有关它们的更多信息,请参见此处:https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
但是,要访问单例,会创建一个特殊的 INSTANCE
对象,处理起来和 Companion
一样麻烦。以下是如何使用注释使其在 Java:
static
感觉
Scenario 4: Using
object
classesKotlin
// There is no more need for the @file:JvmName() annotation. The object class below already handles the proper naming. //This provides a name for this file, so it's not defaulted as [KotlinClassKt] in Java package com.frybits object KotlinClass { //No need for the 'class' keyword here. //Direct access to this variable const val foo: Int = 1 //Tells Java this can be accessed directly from [KotlinClass] @JvmStatic var cat: Int = 9 //Just a function that returns the class name @JvmStatic fun getCustomClassName(): String = this::class.java.simpleName + "boo!" //Getter/Setter access to this variable, but isn't accessible directly from [KotlinClass] var bar: Int = 2 fun someOtherFunction() = "What is 'INSTANCE'?" }
Java
package com.frybits; class JavaClass { void someFunction() { println(KotlinClass.foo); //Direct read of [foo] in [KotlinClass] singleton println(KotlinClass.getCat()); //Getter of [cat] KotlinClass.setCat(0); //Setter of [cat] println(KotlinClass.getCustomClassName()); //Example of using a function of this 'object' class println(KotlinClass.INSTANCE.getBar()); //This is what the singleton would look like without using annotations KotlinClass.INSTANCE.setBar(23); println(KotlinClass.INSTANCE.someOtherFunction()); //Accessing a function in the object class without using annotations } void println(Object o) { System.out.println(o); } }