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

pde*_*eva 543 java kotlin

staticKotlin中没有关键字.

static在Kotlin中表示Java方法的最佳方法是什么?

Mic*_*son 772

您将该函数放在"伴随对象"中.

所以像这样的java代码:

class Foo {
  public static int a() { return 1; }
}
Run Code Online (Sandbox Code Playgroud)

会变成

class Foo {
  companion object {
     fun a() : Int = 1
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以在Kotlin代码中使用它

Foo.a();
Run Code Online (Sandbox Code Playgroud)

但是从Java代码中,您需要将其称为

Foo.Companion.a();
Run Code Online (Sandbox Code Playgroud)

(这也适用于Kotlin.)

如果您不想指定该Companion位,可以添加@JvmStatic注释或命名您的伴侣类.

来自文档:

伴侣对象

可以使用companion关键字标记类中的对象声明:

class MyClass {
   companion object Factory {
       fun create(): MyClass = MyClass()
   }
}
Run Code Online (Sandbox Code Playgroud)

可以通过简单地使用类名作为限定符来调用伴随对象的成员:

val instance = MyClass.create()
Run Code Online (Sandbox Code Playgroud)

...

但是,在JVM上,如果使用@JvmStatic 注释,则可以将伴随对象的成员生成为真正的静态方法和字段.有关更多详细信息,请参阅Java互操作性部分.

添加@JvmStatic注释看起来像这样

class Foo {
  companion object {
    @JvmStatic
    fun a() : Int = 1;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后它将作为一个真正的Java静态函数存在,可以从Java和Kotlin中访问Foo.a().

如果它只是不喜欢该Companion名称,那么您还可以为伴随对象提供如下所示的显式名称:

class Foo {
  companion object Blah {
    fun a() : Int = 1;
  }
}
Run Code Online (Sandbox Code Playgroud)

这将允许你以同样的方式从Kotlin调用它,但是来自java Foo.Blah.a()(它也可以在Kotlin中工作).

  • 我个人认为,这是 Kotlin 为数不多的丑陋之处之一,而 Java 的编写和阅读起来却简单得多。感觉只是——错了。我现在进行了多次 Kotlin 培训,而我所有的学生每次都对此感到困惑。唯一更糟糕的是协程的当前实现(与 C# 中简单的 async/await 相比) (8认同)
  • @DmitryZaitsev _or_ 甚至`fun a() = 1`。 (6认同)
  • 在Kotlin中,它将是`fun a():Int {return 1}`甚至是`fun a():Int = 1` (3认同)
  • @Yajairo87 我认为你要问的太多了,无法在这里发表评论 - 所以我创建了一个直接解决它的问题:/sf/ask/3293253211/一个同伴对象在一个普通对象上 (2认同)

Hen*_* F. 126

Docs建议使用包级函数来解决静态函数的大多数需求.它们只是在源代码文件中的类外声明.可以使用package关键字在文件的开头指定文件包.

宣言

package foo

fun bar() = {}
Run Code Online (Sandbox Code Playgroud)

用法

import foo.bar
Run Code Online (Sandbox Code Playgroud)

另外

import foo.*
Run Code Online (Sandbox Code Playgroud)

您现在可以调用该函数:

bar()
Run Code Online (Sandbox Code Playgroud)

或者如果您不使用import关键字:

foo.bar()
Run Code Online (Sandbox Code Playgroud)

如果未指定包,则可以从根访问该功能.

如果你只有java经验,这看起来有点奇怪.原因是kotlin不是严格的面向对象语言.你可以说它支持类之外的方法.

  • +1用于解释如何在Kotlin**中执行等效权限**而不仅仅是Java中的等效镜像. (23认同)
  • 请注意,在引擎盖下,这些"顶级"或"包"函数实际上被编译到它们自己的类中.在上面的示例中,编译器将创建一个包含所有顶级属性和函数的`类FooPackage`,并将所有引用适当地路由到它们.[来自jetbrains的更多信息.](https://blog.jetbrains.com/kotlin/2015/06/improving-java-interop-top-level-functions-and-properties/) (6认同)
  • 这应该是接受的答案,或者模组应该更新接受的答案以包含包级功能 (2认同)

erl*_*man 25

1.定义:

任何 companion object内部.kt(关键字for methods/variables)将在java中表现为静态.

companion object如果要仅使用包含该对象的类调用方法,请使用a .

class Foo{
companion object {
    fun foo() = println("Foo")
    val bar ="bar"  
    }
}
Run Code Online (Sandbox Code Playgroud)

2.用法:

Foo.foo()        // Outputs Foo    
println(Foo.bar) // Outputs bar
Run Code Online (Sandbox Code Playgroud)

3.输出:

fun foo() = println("Foo")
val bar ="bar"
Run Code Online (Sandbox Code Playgroud)

  • 方法调用需要有``INSTANCE``关键字,如下所示:``Foo.INSTANCE.sayFoo()`` (4认同)

小智 20

使用object来表示val/var /方法来生成静态.您也可以使用object而不是singleton类.如果要在类中创建静态,可以使用伴侣

object Abc{
     fun sum(a: Int, b: Int): Int = a + b
    }
Run Code Online (Sandbox Code Playgroud)


Yog*_*ity 11

顶级/companion object属性static

顶层

当属性与类有些相关时,将它们定义为类声明之前的顶级属性:

const val MAX_ATTEMPTS = 3
private const val DEFAULT_NAME = "Guest"
private const val MIN_AGE = 16

data class User(val id: String, val name: String = DEFAULT_NAME)
Run Code Online (Sandbox Code Playgroud)

这与Java中的属性类似static

当属性完全独立于任何类时,您可以在不包含类的单独文件中将它们定义为顶级。

companion object

当属性与类密切相关并且仅在该类中使用时,请将它们定义在 a 中companion object

data class User(val id: String, val name: String = DEFAULT_NAME) {
    companion object {
        const val DEFAULT_NAME = "Guest"
        const val MIN_AGE = 16
    }
}
Run Code Online (Sandbox Code Playgroud)

顶级/ companion objectforstatic方法

顶层

与上面的属性类似,当函数与类有些相关时,将它们定义在类之上:

fun getAllUsers() { }

fun getProfileFor(userId: String) { }

data class User(val id: String, val name: String)
Run Code Online (Sandbox Code Playgroud)

用法:

val userList = getAllUsers()
Run Code Online (Sandbox Code Playgroud)

companion object

当函数与类密切相关时,将它们定义在 a 中companion object

data class User(val id: String, val name: String) {

    companion object {

        fun getAll() { }

        fun profileFor(userId: String) { }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

val userProfile = User.profileFor("34")
Run Code Online (Sandbox Code Playgroud)

这与Java中的方法类似static

对于 Kotlin 来说,顶级函数通常更惯用。在 中定义函数的一个更好的理由companion object是当您使用 扩展 acompanion objectinterface。单例部分显示了这样的一个示例。


static类的嵌套类

当具有相关功能的类属于一起时,可以通过嵌套将它们分组在一起:

class User(val id: String, val name: String) {
    class UserAccess : UserDao {
        override fun add(user: User) { }
        override fun remove(id: String) { }
    }
}
Run Code Online (Sandbox Code Playgroud)

这相当于staticJava中的嵌套类。这里的类UserAccess实现了一个interface UserDao.

用法:

fun main() {
    val john = User("34", "John")
    val userAccess = User.UserAccess()
    userAccess.add(john)
}
Run Code Online (Sandbox Code Playgroud)

objectstatic INSTANCE

顶层

当您只需要类的单个对象时,您不再需要static INSTANCE像 Java 那样在类内部创建对象。只需使用顶级object声明:

object UserAccess : UserDao {
    override fun add(user: User) { }
    override fun remove(id: String) { }
}
Run Code Online (Sandbox Code Playgroud)

还要注意在单例中扩展 aninterface或 a是多么容易。class

上面的代码在底层生成了以下static INSTANCEJava 单例模式(简化版):

public final class UserAccess implements UserDao {
   public static final UserAccess INSTANCE;

   public void add(User user) { }

   public void remove(String id) { }

   private UserAccess() { }

   static { INSTANCE = new UserAccess();}
}
Run Code Online (Sandbox Code Playgroud)

companion object

当单例与类密切相关时使用companion object

data class User(val id: String, val name: String) {
    companion object : UserDao {
        override fun add(user: User) { }
        override fun remove(id: String) { }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样你就可以得到更优雅的命名:User.add(john)。另外,您还明确表明此单例仅用作该类的实用程序User。如果您想要多个单例或函数/属性组,您也可以在类中使用object不带关键字的 。companion


companion objectstatic工厂用

Koltin 中的工厂函数是使用companion object. 当您想要提供多种方法来创建对象,而对象构造过程很复杂或者多个构造函数表达能力不够时,工厂函数非常有用。

例如,newInstance()以下代码片段中的工厂函数通过自动生成来创建用户id

class User private constructor(val id: Long, val name: String) {
    companion object {
        private var currentId = 0L;
        fun newInstance(name: String) = User(currentId++, name)
    }
}
Run Code Online (Sandbox Code Playgroud)

这相当于staticJava中的工厂方法。

constructor 保留private,但companion object可以访问 constructor

在上面的代码中,id保证了下一代的一致性,因为acompanion object是单例,只有一个对象会跟踪a id,不会有任何重复的id。

另请注意,伴生对象可以具有currentId表示状态的属性(在本例中)。

用法:

val john = User.newInstance("John")
Run Code Online (Sandbox Code Playgroud)

@JvmStatic用于 Java 互操作性

Java 的静态概念在 Kotlin 中不存在。A是一个名为companion object的实数的实例。因此,当您从 Java 调用 Kotlin 代码时,该类的对象首先在幕后实例化。您需要使用Java 中的对象来调用该函数:classCompanionCompanionCompanion

Profile userProfile = User.Companion.profileFor("34");
Run Code Online (Sandbox Code Playgroud)

为了使用惯用的 Java 命名方式并减少冗长,请@JvmStatic在该函数或属性上使用注释:

companion object {
    @JvmStatic
    fun profileFor(userId: String): Profile { }
}
Run Code Online (Sandbox Code Playgroud)

@JvmStatic注释创建staticgetProfileFor()函数的单独的纯副本。现在您可以通过 Java 使用常规语法来使用它:

Profile userProfile = User.profileFor("34");
Run Code Online (Sandbox Code Playgroud)

就是这样!希望这些示例对您的项目有用。


Sam*_*uel 9

这也对我有用

object Bell {
    @JvmStatic
    fun ring() { }
}
Run Code Online (Sandbox Code Playgroud)

来自Kotlin

Bell.ring()
Run Code Online (Sandbox Code Playgroud)

来自Java

Bell.ring()
Run Code Online (Sandbox Code Playgroud)


And*_*eek 9

在 Kotlin 中应用静态有 2 种方法

首先在类下创建一个伴生对象

例如:

class Test{
  companion object{
    fun isCheck(a:Int):Boolean{
      if(a==0) true else false
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

你可以将此函数称为

Test.Companion.isCheck(2)
Run Code Online (Sandbox Code Playgroud)

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

object Test{
  fun isCheck(a:Int):Boolean{
    if(a==0) true else false     
  }
}
Run Code Online (Sandbox Code Playgroud)

快乐编码!


Pab*_*ter 7

尽管这已经有 2 年多的历史了,并且有很多很好的答案,但我发现缺少其他一些获取“静态”Kotlin 字段的方法。这是 Kotlin-Javastatic互操作的示例指南:

场景 1:在 Kotlin for Java 中创建静态方法

科特林

@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
    }
}
Run Code Online (Sandbox Code Playgroud)

爪哇

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

迈克尔安德森的回答提供了比这更深入的内容,并且绝对应该在这种情况下被引用。


下一个场景处理在 Kotlin 中创建静态字段,以便 Java 不必继续调用KotlinClass.foo()那些不需要静态函数的情况。

场景 2:在 Kotlin for Java 中创建静态变量

科特林

@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
    }
}
Run Code Online (Sandbox Code Playgroud)

爪哇

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Kotlin 的一大特色是您可以创建顶级函数和变量。这使得创建常量字段和函数的“无类”列表非常有用,这些列表又可以用作staticJava 中的函数/字段。

场景 3:从 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!")
}
Run Code Online (Sandbox Code Playgroud)

爪哇

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

另一个可以在 Java 中用作“静态”字段的值得注意的是 Kotlinobject类。这些是零参数单例类,在第一次使用时被延迟实例化。关于它们的更多信息可以在这里找到:https : //kotlinlang.org/docs/reference/object-declarations.html#object-declarations

但是,为了访问单例,INSTANCE会创建一个特殊的对象,处理起来同样麻烦Companion。以下是如何使用注释static在 Java 中赋予它干净的感觉:

场景 4:使用object

科特林

@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'?"
}
Run Code Online (Sandbox Code Playgroud)

爪哇

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 7

只需使用这种方法

object Foo{
   fun foo() = println("Foo")
   val bar ="bar"  
}

Foo.INSTANCE.foo()
Run Code Online (Sandbox Code Playgroud)


小智 6

object objectName {
    fun funName() {

    }
}
Run Code Online (Sandbox Code Playgroud)

  • 尽管此代码段可能是解决方案,但是[包括说明](https://meta.stackexchange.com/questions/114762/explaining-entirely-%E2%80%8C%E2%80%8Bcode-based-answers)确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。 (4认同)

Raj*_*iya 5

您需要为静态方法传递伴随对象,因为kotlin没有static关键字-可以通过仅使用类名作为限定符来调用伴随对象的成员:

package xxx
    class ClassName {
              companion object {
                       fun helloWord(str: String): String {
                            return stringValue
                      }
              }
    }
Run Code Online (Sandbox Code Playgroud)