What is the equivalent of Java static methods in Kotlin?
Kotlin中没有
在Kotlin中表示EDCOX1×0的Java方法的最佳方式是什么?
将函数放在"伴生对象"中。
所以Java代码是这样的:
1 2 3 | class Foo { public static int a() { return 1; } } |
将成为
1 2 3 4 5 | class Foo { companion object { fun a() : Int = 1 } } |
号
然后您可以从Kotlin代码内部使用它作为
1 | Foo.a(); |
但是从Java代码内部,您需要调用它作为
1 | Foo.Companion.a(); |
。
(也适用于Kotlin内部。)
如果不想指定
从文档中:
Companion Objects
An object declaration inside a class can be marked with the companion
keyword:
1
2
3
4
5 class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}Members of the companion object can be called by using simply the class
name as the qualifier:
1 val instance = MyClass.create()...
However, on the JVM you can have members of companion objects generated
as real static methods and fields, if you use the@JvmStatic
annotation. See the Java interoperability section for more details.
号
添加EDOCX1[1]注释如下所示
1 2 3 4 5 6 | class Foo { companion object { @JvmStatic fun a() : Int = 1; } } |
然后它将作为一个真正的Java静态函数存在,从Java和Kotlin都是EDCOX1,3。
如果你只是不喜欢
1 2 3 4 5 | class Foo { companion object Blah { fun a() : Int = 1; } } |
。
你也可以用同样的方式从科特林那里叫它,但是从Java,像EDCOX1,5,(也将在Kotlin工作)。
Docs建议使用包级功能来解决对静态功能的大部分需求。它们只是在源代码文件中的类外部声明的。可以在带有package关键字的文件开头指定文件的包。
宣言
1 2 3 | package foo fun bar() = {} |
。
用法
1 | import foo.bar |
或者
1 | import foo.* |
。
现在可以使用以下命令调用函数:
1 | bar() |
号
或者如果不使用import关键字:
1 | foo.bar() |
号
如果不指定包,则可以从根目录访问函数。
如果您只对Java有经验,这可能有点奇怪。原因是Kotlin不是一种严格的面向对象的语言。可以说它支持类之外的方法。
使用
1 2 3 4 5 6 | class Foo{ companion object { fun sayFoo() = println("Foo") val bar ="bar" } } |
。
2。用途:
1 2 | Foo.sayFoo() // Output Foo println(Foo.bar) . // Output Bar |
使用对象来表示val/var/方法以使其成为静态的。也可以使用对象而不是单例类。如果你想在类内实现静态,可以使用伴侣。
1 2 3 | object Abc{ fun sum(a: Int, b: Int): Int = a + b } |
号
如果需要从Java调用它:
1 | int z = Abc.INSTANCE.sum(x,y); |
号
在Kotlin中,忽略实例。
这对我也有用
1 2 3 4 | object Bell { @JvmStatic fun ring() { } } |
。
来自科特林
1 | Bell.ring() |
从Java
1 | Bell.ring() |
您需要为静态方法传递伴生对象,因为Kotlin没有静态关键字-仅使用类名作为限定符即可调用伴生对象的成员:
1 2 3 4 5 6 7 8 |
号
有两种方法可以在Kotlin中应用静态
首先在类下生成一个伴生对象
例如:
1 2 3 4 5 6 7 |
号
您可以将此函数称为
1 | Test.Companion.isCheck(2) |
号
我们可以使用的另一种方法是创建一个对象类
1 2 3 4 5 |
号
编码愉快!
1 2 3 4 5 | object objectName { fun funName() { } } |
号
Kotlin没有任何静态关键字。你用Java
1 2 3 4 5 | class AppHelper { public static int getAge() { return 30; } } |
还有科特林
1 2 3 4 5 | class AppHelper { companion object { fun getAge() : Int = 30 } } |
号
调用Java
1 | AppHelper.getAge(); |
号
呼叫Kotlin
1 | AppHelper.Companion.getAge(); |
我认为它工作得很好。
我想在上面的答案中加些东西。
是的,您可以在源代码文件(类外)中定义函数。但是,如果使用伴生对象在类内定义静态函数更好,因为可以通过利用Kotlin扩展来添加更多的静态函数。
1 2 3 4 5 6 7 8 9 10 | class MyClass { companion object { //define static functions here } } //Adding new static function fun MyClass.Companion.newStaticFunction() { // ... } |
号
您可以调用上面定义的函数,因为您将调用伴生对象中的任何函数。
为了简短起见,您可以使用"伴生对象"进入Kotlin静态世界,例如:
1 2 3 4 | companion object { const val TAG ="tHomeFragment" fun newInstance() = HomeFragment() } |
要使常量字段像代码中那样使用"const val"
只需创建一个伴生对象并将函数放入其中
1 2 3 4 5 6 |
。
要从Kotlin类调用方法,请执行以下操作:
1 2 3 4 5 | class KotlinClass{ fun main(args : Array<String>) { UtilClass.repeatIt5Times("Hello") } } |
号
或使用导入
1 2 3 4 5 6 | import Packagename.UtilClass.Companion.repeatIt5Times class KotlinClass{ fun main(args : Array<String>) { repeatIt5Times("Hello") } } |
号
从Java类调用该方法:
1 2 3 4 5 | class JavaClass{ public static void main(String [] args){ UtilClass.Companion.repeatIt5Times("Hello"); } } |
或者在方法中添加@jvmstatic注释
1 2 3 4 5 |
或者通过在方法中添加@ jvMstatic注释并在Java中实现静态导入
1 2 3 4 5 6 | import static Packagename.UtilClass.repeatIt5Times class JavaClass{ public static void main(String [] args){ repeatIt5Times("Hello") } } |
伙伴对象是Java静态关键字的替代,可以通过声明它们作为伙伴对象来将类或方法设为静态。如果从同一个类中调用伴生对象,也不需要用类名来限定它们。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class SomeClass() { val id: Int init { id = nextId++ } private companion object { var nextId = 1 } } fun main(args: Array<String>) { repeat(2) { println(SomeClass().id) } } |
号
可以使用伴生对象以外的对象
1 2 3 | object Utils { fun someFunction() } |
。
因此,当调用该方法时,会出现这种情况。
1 | Utils.someFunction() |
尽管这已经2岁多一点了,而且有很多很好的答案,但是我看到了一些其他获得"静态"Kotlin场的方法不见了。下面是KTLLIN Java EDCOX1 0接口的示例指南:
Scenario 1: Creating a static method in Kotlin for Java
Kotlin
1
2
3
4
5
6
7
8
9
10
11
12
13
14 @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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 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就不必在不需要静态函数的情况下继续调用EDCOX1 OR 1了。
Scenario 2: Creating a static variable in Kotlin for Java
Kotlin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 @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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 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的一个重要特性是您可以创建顶级函数和变量。这使得创建恒定字段和函数的"无类"列表变得更为可喜,而这些字段又可以作为Java中的EDCOX1和0个函数/字段。
Scenario 3: Accessing top level fields and functions in Kotlin from Java
Kotlin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 //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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 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 EDCOX1,3个类。这些是零参数的单例类,在第一次使用时被延迟地实例化。关于它们的更多信息可以在这里找到:https://kotlinlang.org/docs/reference/object declarations.html object declarations
然而,为了访问singleton,创建了一个特殊的
Scenario 4: Using
object classesKotlin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 @file:JvmName("KotlinClass")
//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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 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);
}
}
号
使用"伴生对象或命名对象"中的函数。
参见伴生对象示例:
1 2 3 4 5 | class Foo { companion object { fun square(x : Int) : Int = x*x } } |
号
参见命名对象的示例
1 2 3 | object Foo{ fun square(x : Int) : Int = x*x } |
号
您可以使用
1 | val k = Foo.square(12) |
Java静态方法与KoTrin等价物的精确转换将是这样的。例如,在UTL类中有一个静态方法,在Java和KOTLIN中都是等价的。使用@jvmstatic非常重要。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
生成一个伴生对象并用jvmsstatic注释标记该方法
直接将它们写入文件。
在Java中(丑陋):
1 2 3 4 | package xxx; class XxxUtils { public static final Yyy xxx(Xxx xxx) { return xxx.xxx(); } } |
号
在科特林:
1 2 3 | @file:JvmName("XxxUtils") package xxx fun xxx(xxx: Xxx): Yyy = xxx.xxx() |
号
这两个代码在编译后相等(即使是编译后的文件名,也使用
让,你有一个班学生。还有一个静态方法getuniversityname()&;一个名为totalstudent的静态字段。
您应该在类内声明伴生对象块。
1 2 3 | companion object { // define static method & field here. } |
那么你的课看起来像
1 2 3 4 5 6 7 8 9 10 11 12 |
号
然后您可以这样使用这些静态方法和字段。
1 2 3 | println("University :" + Student.getUniversityName() +", Total Student:" + Student.totalStudent) // Output: // University : MBSTU, Total Student: 30 |
使用
1 2 3 4 5 6 7 8 9 10 11 12 |
号
对于Java:
1 2 | public class Constants { public static final long MAX_CLICK_INTERVAL = 1000;} |
等效Kotlin代码:
1 2 |
号
因此,Java静态方法相当于Kotlin中的对象类。
所有静态构件和功能都应在配对块内。
1 2 3 4 5 6 7 8 | companion object { @JvmStatic fun main(args: Array<String>) { } fun staticMethod() { } } |
Java代码如下:
1 | class Foo { public static int a() { return 1; } } |
号
在Kotlin将变成如下:
1 | class Foo { companion object { fun a() : Int = 1 } } |
号
但是,在jvm上使用@jvm static注释,我们可以将伴生对象的成员生成为真正的静态方法和字段。
很多人提到伴生对象,这是正确的。但是,正如您所知道的,您也可以使用任何类型的对象(使用对象关键字,而不是类),即,
号
就像Java中的静态方法一样使用它:
1 | StringUtils.toUpper("foobar") |
然而,这种模式在Kotlin中是无用的,它的一个优点是它不再需要用静态方法填充类。根据您的用例,使用全局、扩展和/或本地函数更为合适。在我工作的地方,我们通常在一个单独的平面文件中使用命名约定[classname]extensions.kt(即fooextensions.kt)定义全局扩展函数。但更典型的情况是,我们在操作类或对象中需要函数的地方编写函数。
您可以通过伴生对象实现Kotlin中的静态功能。
- 向对象声明添加伴生允许添加对象的静态功能,即使实际静态Kotlin中不存在概念。
- 伴生对象也可以访问类的所有成员,包括私有构造函数。
- 当类被实例化时,一个伴生对象被初始化。
不能在类外部声明伴生对象。
1
2
3
4
5
6
7
8
9
10
11
12class MyClass{
companion object {
val staticField ="This is an example of static field Object Decleration"
fun getStaticFunction(): String {
return"This is example of static function for Object Decleration"
}
}
}。
- 使用包级别功能。
- 使用伴生对象。
小精灵
可以使用类名称作为限定符来调用伴生对象的成员:
输出:
1 2 3 | MyClass.staticField // This is an example of static field Object Decleration MyClass.getStaticFunction() : // This is an example of static function for Object Decleration |
。
您可以使用伴生对象-Kotlinlang
它可以通过首先创建该接口来显示
1 2 3 | interface I<T> { } |
。
然后我们必须在该接口内部创建一个函数:
1 | fun SomeFunc(): T |
号
之后,我们需要一门课:
1 | class SomeClass {} |
号
在该类中,我们需要该类中的一个伴生对象:
1 | companion object : I<SomeClass> {} |
在这个伴生对象中,我们需要旧的
1 | override fun SomeFunc(): SomeClass = SomeClass() |
最后,在所有这些工作之后,我们需要一些东西来驱动静态函数,我们需要一个变量:
1 | var e:I<SomeClass> = SomeClass() |
您可以执行以下操作: