在Kotlin中没有静态关键字。

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


当前回答

所有静态成员和函数都应该在伴生块中

  companion object {
    @JvmStatic
    fun main(args: Array<String>) {
    }

    fun staticMethod() {
    }
  }

其他回答

这对我也有用

object Bell {
    @JvmStatic
    fun ring() { }
}

从芬兰湾的科特林

Bell.ring()

从Java

Bell.ring()
object objectName {
    fun funName() {

    }
}

你把函数放在“同伴对象”中。

java代码是这样的:

class Foo {
  public static int a() { return 1; }
}

将成为

class Foo {
  companion object {
     fun a() : Int = 1
  }
}

然后,您可以在Kotlin代码中作为

Foo.a();

但是在Java代码中,您需要将其调用为

Foo.Companion.a();

(也可以在Kotlin内部工作。)

如果您不喜欢指定Companion位,您可以添加@JvmStatic注释或命名您的Companion类。

从文档中可以看出:

Companion Objects An object declaration inside a class can be marked with the companion keyword: 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: 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.

添加@JvmStatic注释如下所示

class Foo {
  companion object {
    @JvmStatic
    fun a() : Int = 1;
  }
}

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

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

class Foo {
  companion object Blah {
    fun a() : Int = 1;
  }
}

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

在Java中,我们可以这样写

class MyClass {
  public static int myMethod() { 
  return 1;
  }
}

在Kotlin中,我们可以用下面的方式写

class MyClass {
  companion object {
     fun myMethod() : Int = 1
  }
}

在Kotlin中,一个同伴被用作静态。

静态属性的顶级/伴生对象

顶级

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

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)

这类似于Java中的静态属性。

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

伴星

当属性与类密切相关并且只会在该类中使用时,在伴随对象中定义它们:

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

用于静态方法的顶级/伴生对象

顶级

类似于上面的属性,当函数与类有点关联时,将它们定义在类的上方:

fun getAllUsers() { }

fun getProfileFor(userId: String) { }

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

用法:

val userList = getAllUsers()

伴星

当函数与类密切相关时,在伴随对象中定义它们:

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

    companion object {

        fun getAll() { }

        fun profileFor(userId: String) { }
    }
}

用法:

val userProfile = User.profileFor("34")

这类似于Java中的静态方法。

顶级函数对于Kotlin来说通常更习惯。在伴生对象中定义函数的一个更好的原因是当您使用接口扩展伴生对象时。在单例部分中展示了一个示例。


静态类的嵌套类

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

class User(val id: String, val name: String) {
    class UserAccess : UserDao {
        override fun add(user: User) { }
        override fun remove(id: String) { }
    }
}

这相当于Java中的静态嵌套类。这里的UserAccess类实现了一个接口UserDao。

用法:

fun main() {
    val john = User("34", "John")
    val userAccess = User.UserAccess()
    userAccess.add(john)
}

用于静态INSTANCE的单例对象

顶级

当您只想要类的单个对象时,您不再需要像在Java中那样在类中创建静态INSTANCE。简单地使用顶级对象声明:

object UserAccess : UserDao {
    override fun add(user: User) { }
    override fun remove(id: String) { }
}

还要注意在单例中扩展接口或类是多么容易。

上面的代码,在底层,在Java中产生以下静态INSTANCE单例模式(简化):

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();}
}

伴星

当单例对象与类密切相关时,使用companion对象:

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

这样可以获得更优雅的命名:User.add(john)。另外,您要明确这个单例只用作User类的实用程序。如果需要多个单例对象或函数/属性组,也可以在类中使用不带companion关键字的对象。


静态工厂的伴生对象

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

例如,下面代码段中的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)
    }
}

这相当于Java中的静态工厂方法。

构造函数是私有的,但是伴生对象可以访问构造函数。

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

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

用法:

val john = User.newInstance("John")

@JvmStatic用于Java互操作性

Java的静态概念在Kotlin中并不存在。同伴对象是一个称为companion的真实类的实例。因此,当您从Java调用Kotlin代码时,Companion类的对象首先在后台实例化。你需要在Java中使用Companion对象调用该函数:

Profile userProfile = User.Companion.profileFor("34");

为了获得惯用的Java命名和更少的冗长,可以在函数或属性上使用@JvmStatic注释:

companion object {
    @JvmStatic
    fun profileFor(userId: String): Profile { }
}

@JvmStatic注释创建getProfileFor()函数的一个单独的纯静态副本。现在你可以在Java中使用常规语法:

Profile userProfile = User.profileFor("34");

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