什么是Kotlin中的Java静态方法?

What is the equivalent of Java static methods in Kotlin?

Kotlin中没有static关键字。

在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位,可以添加@JvmStatic注释或命名伴生类。

从文档中:

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。

如果你只是不喜欢Companion这个名字,那么你也可以为伴生对象提供一个显式名称,如下所示:

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不是一种严格的面向对象的语言。可以说它支持类之外的方法。


使用companion object将静态方法/变量括起来

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
package xxx
    class ClassName {
              companion object {
                       fun helloWord(str: String): String {
                            return stringValue
                      }
              }
    }


有两种方法可以在Kotlin中应用静态

首先在类下生成一个伴生对象

例如:

1
2
3
4
5
6
7
class Test{
    companion object{
          fun isCheck(a:Int):Boolean{
             if(a==0) true else false
          }
     }
}

您可以将此函数称为

1
Test.Companion.isCheck(2)

我们可以使用的另一种方法是创建一个对象类

1
2
3
4
5
object Test{
       fun isCheck(a:Int):Boolean{
            if(a==0) true else false
       }
}

编码愉快!


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
  class UtilClass {
        companion object {
  //        @JvmStatic
            fun repeatIt5Times(str: String): String = str.repeat(5)
        }
    }

要从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
class JavaClass{
   public static void main(String [] args){
     UtilClass.repeatIt5Times("Hello")
   }
}

或者通过在方法中添加@ 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,创建了一个特殊的INSTANCE对象,这和Companion一样麻烦。下面是如何使用注解给它干净的EDCOX1 0在Java中的感觉:

Scenario 4: Using object classes

Kotlin

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
 //Java
class Util{
     public static String capitalize(String text){
     return text.toUpperCase();}
   }



//Kotlin
class Util {
    companion object {
        @JvmStatic
        fun capitalize(text:String): String {
            return text.toUpperCase()
        }
    }
}

生成一个伴生对象并用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()

这两个代码在编译后相等(即使是编译后的文件名,也使用file:JvmName来控制编译后的文件名,它应该放在包名声明之前)。


让,你有一个班学生。还有一个静态方法getuniversityname()&;一个名为totalstudent的静态字段。

您应该在类内声明伴生对象块。

1
2
3
companion object {
 // define static method & field here.
}

那么你的课看起来像

1
2
3
4
5
6
7
8
9
10
11
12
    class Student(var name: String, var city: String, var rollNumber: Double = 0.0) {

    // use companion object structure
    companion object {

        // below method will work as static method
        fun getUniversityName(): String ="MBSTU"

        // below field will work as static field
        var totalStudent = 30
    }
}

然后您可以这样使用这些静态方法和字段。

1
2
3
println("University :" + Student.getUniversityName() +", Total Student:" + Student.totalStudent)
    // Output:
    // University : MBSTU, Total Student: 30

使用@JVMStatic注释

1
2
3
4
5
6
7
8
9
10
11
12
companion object {

    // TODO: Rename and change types and number of parameters
    @JvmStatic
    fun newInstance(param1: String, param2: String) =
            EditProfileFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                    putString(ARG_PARAM2, param2)
                }
            }
}


对于Java:

1
2
public class Constants {
public static final long MAX_CLICK_INTERVAL = 1000;}

等效Kotlin代码:

1
2
object  Constants {
const val MAX_CLICK_INTERVAL: Long = 1000}

因此,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注释,我们可以将伴生对象的成员生成为真正的静态方法和字段。


很多人提到伴生对象,这是正确的。但是,正如您所知道的,您也可以使用任何类型的对象(使用对象关键字,而不是类),即,

1
2
3
object StringUtils {
    fun toUpper(s: String) : String { ... }
}

就像Java中的静态方法一样使用它:

1
StringUtils.toUpper("foobar")

然而,这种模式在Kotlin中是无用的,它的一个优点是它不再需要用静态方法填充类。根据您的用例,使用全局、扩展和/或本地函数更为合适。在我工作的地方,我们通常在一个单独的平面文件中使用命名约定[classname]extensions.kt(即fooextensions.kt)定义全局扩展函数。但更典型的情况是,我们在操作类或对象中需要函数的地方编写函数。


您可以通过伴生对象实现Kotlin中的静态功能。

  • 向对象声明添加伴生允许添加对象的静态功能,即使实际静态Kotlin中不存在概念。
  • 伴生对象也可以访问类的所有成员,包括私有构造函数。
  • 当类被实例化时,一个伴生对象被初始化。
  • 不能在类外部声明伴生对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class 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> {}

    在这个伴生对象中,我们需要旧的SomeFunc功能,但我们需要超越它:

    1
    override fun SomeFunc(): SomeClass = SomeClass()

    最后,在所有这些工作之后,我们需要一些东西来驱动静态函数,我们需要一个变量:

    1
    var e:I<SomeClass> = SomeClass()

    您可以执行以下操作:

  • 使用包级别功能。
  • 使用伴生对象。