【问题标题】:What is the equivalent of Java static methods in Kotlin?Kotlin 中 Java 静态方法的等价物是什么?
【发布时间】:2017-03-14 03:44:56
【问题描述】:

Kotlin 中没有 static 关键字。

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

【问题讨论】:

  • 请注意: Kotlin 已移除 Java 风格的静态,以鼓励更可维护(我敢说“更好”)的编码实践。静态全局变量通常违反 OOP 范式,但它们非常方便。因此,Kotlin 为我们提供了companions, a more OOP-friendly way of having statics.
  • @NicholasMiller 为什么它对 OOP 更友好?我认为如果没有反复出现的静态注释(样板文件),它更容易阅读和写作。还是有其他好的理由?
  • 乍一看,这似乎正是 Scala 的伴生类。这符合我的印象:kotlin 是一个更简单的 scala 。这很好。
  • @TorbenG。样板代码是您每次使用全局静态时都会受到惩罚的教育障碍。现代语言是保姆语言。

标签: java kotlin static


【解决方案1】:

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

所以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 注释或命名您的伴随类。

来自docs

伴随对象

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

class MyClass {
   companion object Factory {
       fun create(): MyClass = MyClass()
   }
}

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

val instance = MyClass.create()

...

但是,在 JVM 上,您可以生成伴随对象的成员 作为真正的静态方法和字段,如果您使用 @JvmStatic 注解。有关详细信息,请参阅Java interoperability 部分。

添加@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 调用它,但是 来自 Foo.Blah.a() 之类的 java(也适用于 Kotlin)。

【讨论】:

  • 在 Kotlin 中它将是 fun a(): Int { return 1 } 甚至是 fun a(): Int = 1
  • @DmitryZaitsev 甚至fun a() = 1
  • @Yajairo87 我认为您的要求太多了,无法在此处的评论中涵盖 - 所以我创建了一个直接解决它的问题:stackoverflow.com/questions/47046474/…
  • IHMO 这是 Kotlin 为数不多的丑陋之处之一,Java 的编写和阅读都更加简单。感觉只是——错了。我现在进行了多次 Kotlin 培训,我所有的学生每次都对此感到困惑。唯一更糟糕的是协程的当前实现(与 C# 中非常简单的 async/await 相比)
  • @Novaterata Pablo Baxter 给出了一个很好的答案,其中包含相当深入的一些其他选项。 (stackoverflow.com/a/54975004/221955) 和 Yogesh Umesh Vaity (stackoverflow.com/a/66175395/221955) 的类似回答。正如你所说,在这里包含一些信息会很好。如果他们缺少您知道的其他选项,请告诉我,我会在此处添加。
【解决方案2】:

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

声明

package foo

fun bar() = {}

用法

import foo.bar

或者

import foo.*

您现在可以使用以下方法调用该函数:

bar()

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

foo.bar()

如果您不指定包,则可以从根目录访问该函数。

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

编辑: 他们已经编辑了文档,不再包含关于推荐包级功能的句子。 This 是上面提到的原件。

【讨论】:

  • 请注意,这些“顶级”或“包”函数实际上被编译到它们自己的类中。在上面的示例中,编译器将创建一个包含所有顶级属性和函数的class FooPackage,并适当地将所有引用路由到它们。 More info from jetbrains.
  • +1 用于解释如何在在 Kotlin 中做同样的事情,而不仅仅是在 Java 中的镜像。
  • 这应该是接受的答案,或者模组应该更新接受的答案以包含包级功能
  • @MitchellTracy 非常棒的信息!谢谢。
  • 这是迄今为止更好的解决方案。只是想澄清一下,您在哪里定义函数 bar() 与文件名无关,您可以将其命名为 BarUtils.kt 或其他任何名称,然后如正文所述,您将使用 import <package name>.bar 导入它
【解决方案3】:

A.旧 Java 方式:

  1. 声明一个companion object 来包含一个静态方法/变量

    class Foo{
    companion object {
        fun foo() = println("Foo")
        val bar ="bar"  
        }
    }
    
  2. 使用:

    Foo.foo()        // Outputs Foo    
    println(Foo.bar) // Outputs bar
    


B.新的 Kotlin 方式

  1. .kt 文件上无类直接在文件上声明。

    fun foo() = println("Foo")
    val bar ="bar"
    
  2. 使用methods/variables 及其名称。 (导入后

    使用:

    foo()        // Outputs Foo          
    println(bar) // Outputs bar     
    

【讨论】:

  • 如果我试图在其他类中初始化它会给出 java.lang.ExceptionInInitializerError 并且我使用 var 而不是 val
  • 方法调用需要有INSTANCE关键字,像这样:Foo.INSTANCE.sayFoo()
  • 如果您想要static CLASS 而不仅仅是static methdos,我认为此解决方案是首选方式。因为有了伴生对象,你仍然可以实例化父类。
  • val 不是静态的,它相当于 Java 中的 static final
【解决方案4】:

使用 object 表示 val/var/method 来做静态。您也可以使用对象而不是单例类。如果您想在类中设置静态,可以使用 companion

object Abc{
     fun sum(a: Int, b: Int): Int = a + b
    }

如果你需要从 Java 中调用它:

int z = Abc.INSTANCE.sum(x,y);

在 Kotlin 中,忽略 INSTANCE。

【讨论】:

  • 这就是我要找的,谢谢:D
  • 在 Java 中,我可以在不使用 INSTANCE 的情况下将实例变量引用为类变量,我害怕这种行为。
【解决方案5】:

这对我也有用

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

来自科特林

Bell.ring()

来自Java

Bell.ring()

【讨论】:

    【解决方案6】:
    object objectName {
        fun funName() {
    
        }
    }
    

    【讨论】:

    • 虽然此代码 sn-p 可能是解决方案,但 including an explanation 确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
    【解决方案7】:

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

    场景 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
        }
    }
    

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

    Michael Anderson 的回答提供了比这更深入的内容,绝对应该在这种情况下参考。


    下一个场景处理在 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
        }
    }
    

    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 的一大特色是您可以创建顶级函数和变量。这使得创建常量字段和函数的“无类”列表变得更好,而这些列表又可以用作 Java 中的 static 函数/字段。

    场景 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!")
    }
    

    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 感觉:

    场景 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'?"
    }
    

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

    【讨论】:

      【解决方案8】:

      Kotlin 没有任何静态关键字。您可以将以下代码用于 Java 和 Kotlin

       object AppHelper {
          @JvmStatic
          fun getAge() : Int = 30
      }
      

      调用 Java 类

      AppHelper.getAge();
      

      调用 Kotlin 课程

      AppHelper.getAge()
      

      它非常适合我。谢谢

      【讨论】:

        【解决方案9】:

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

        package xxx
            class ClassName {
                      companion object {
                               fun helloWord(str: String): String {
                                    return stringValue
                              }
                      }
            }
        

        【讨论】:

          【解决方案10】:

          顶级/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)
          

          这类似于 Java 中的 static 属性。

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

          companion object

          当属性与一个类密切相关并且只在该类中使用时,在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
              }
          }
          

          顶级/companion object 用于static 方法

          顶级

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

          fun getAllUsers() { }
          
          fun getProfileFor(userId: String) { }
          
          data class User(val id: String, val name: String)
          

          用法:

          val userList = getAllUsers()
          

          companion object

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

          data class User(val id: String, val name: String) {
          
              companion object {
          
                  fun getAll() { }
          
                  fun profileFor(userId: String) { }
              }
          }
          

          用法:

          val userProfile = User.profileFor("34")
          

          这类似于 Java 中的 static 方法。

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


          static 类的嵌套类

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

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

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

          用法:

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

          单例objectstatic INSTANCE

          顶级

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

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

          还要注意在单例中扩展 interfaceclass 是多么容易。

          上面的代码在后台生成了以下static INSTANCE Java 中的单例模式(简化):

          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 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) { }
              }
          }
          

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


          companion objectstatic 工厂

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

          例如下面sn -p中的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 中的 static 工厂方法。

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

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

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

          用法:

          val john = User.newInstance("John")
          

          @JvmStatic 用于 Java 互操作性

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

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

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

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

          @JvmStatic 注释创建了 getProfileFor() 函数的单独的纯 static 副本。现在您可以使用常规语法从 Java 中使用它:

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

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

          【讨论】:

          • 答案写得很好,很详细。
          【解决方案11】:

          只需创建一个伴生对象并将函数放入其中

            class UtilClass {
                  companion object {
            //        @JvmStatic
                      fun repeatIt5Times(str: String): String = str.repeat(5)
                  }
              }
          

          从 kotlin 类调用方法:

          class KotlinClass{
            fun main(args : Array<String>) { 
              UtilClass.repeatIt5Times("Hello")
            }
          }
          

          或使用导入

          import Packagename.UtilClass.Companion.repeatIt5Times
          class KotlinClass{
            fun main(args : Array<String>) { 
               repeatIt5Times("Hello")
            }
          }
          

          从 java 类调用方法:

           class JavaClass{
              public static void main(String [] args){
                 UtilClass.Companion.repeatIt5Times("Hello");
              }
           }
          

          或者通过给方法添加@JvmStatic注解

          class JavaClass{
             public static void main(String [] args){
               UtilClass.repeatIt5Times("Hello")
             }
          }
          

          或者两者都通过在方法中添加@JvmStatic注解并在java中进行静态导入

          import static Packagename.UtilClass.repeatIt5Times
          class JavaClass{
             public static void main(String [] args){
               repeatIt5Times("Hello")
             }
          }
          

          【讨论】:

            【解决方案12】:

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

            先在类下做一个伴生对象

            例如:

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

            你可以把这个函数称为

            Test.Companion.isCheck(2)
            

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

            object Test{
                   fun isCheck(a:Int):Boolean{
                        if(a==0) true else false
                   }
            }
            

            编码愉快!

            【讨论】:

            • 首次使用(即Test.Companion.isCheck(2))IDE 显示警告并说Companion reference is redundant。可以简化为Test.isCheck(2),简化后的形式更接近java等价物。
            【解决方案13】:

            我想在上面的答案中添加一些内容。

            是的,您可以在源代码文件(类外)中定义函数。但是,如果您使用 Companion Object 在类中定义静态函数会更好,因为您可以通过利用 Kotlin Extensions 添加更多静态函数。

            class MyClass {
                companion object { 
                    //define static functions here
                } 
            }
            
            //Adding new static function
            fun MyClass.Companion.newStaticFunction() {
                // ...
            }
            

            您可以调用上面定义的函数,因为您将调用 Companion Object 中的任何函数。

            【讨论】:

              【解决方案14】:

              对于 Java:

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

              等效的 Kotlin 代码:

              object  Constants {
              const val MAX_CLICK_INTERVAL: Long = 1000}
              

              所以在 Kotlin 中相当于 Java 的静态方法是对象类。

              【讨论】:

                【解决方案15】:

                为了简短起见,您可以使用 "companion object" 进入 Kotlin 静态世界,例如:

                  companion object {
                    const val TAG = "tHomeFragment"
                    fun newInstance() = HomeFragment()
                }
                

                并在代码中使用 "const val" 来制作常量字段。 但尽量避免使用静态类,因为它在使用 Mockito! 进行单元测试时遇到困难。

                【讨论】:

                  【解决方案16】:

                  对于 Android 使用字符串从单个活动到所有必要活动。 就像java中的静态

                  public final static String TEA_NAME = "TEA_NAME";

                  Kotlin 中的等效方法:

                  class MainActivity : AppCompatActivity() {
                      companion object {
                          const val TEA_NAME = "TEA_NAME"
                      }
                      override fun onCreate(savedInstanceState: Bundle?) {
                          super.onCreate(savedInstanceState)
                          setContentView(R.layout.activity_main)
                      }
                  }
                  

                  另一个需要价值的活动:

                  val teaName = MainActivity.TEA_NAME
                  

                  【讨论】:

                    【解决方案17】:

                    java 静态方法到 kotlin 等效方法的精确转换是这样的。例如这里的 util 类有一个静态方法,它在 java 和 kotlin 中都是等效的。 @JvmStatic 的使用很重要。

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

                    【讨论】:

                      【解决方案18】:

                      除了迈克尔安德森的回答,我在我的项目中使用其他两种方式进行编码。

                      第一:

                      您可以将所有变量归为一类。 创建了一个名为 Const 的 kotlin 文件

                      object Const {
                          const val FIRST_NAME_1 = "just"
                          const val LAST_NAME_1 = "YuMu"
                      }
                      

                      你可以在kotlin和java代码中使用它

                       Log.d("stackoverflow", Const.FIRST_NAME_1)
                      

                      第二:

                      您可以使用 Kotlin 的扩展功能
                      创建了一个名为 Ext 的 kotlin 文件,下面的代码是 Ext 文件中的所有代码

                      package pro.just.yumu
                      
                      /**
                       * Created by lpf on 2020-03-18.
                       */
                      
                      const val FIRST_NAME = "just"
                      const val LAST_NAME = "YuMu"
                      

                      你可以在 kotlin 代码中使用它

                       Log.d("stackoverflow", FIRST_NAME)
                      

                      你可以在java代码中使用它

                       Log.d("stackoverflow", ExtKt.FIRST_NAME);
                      

                      【讨论】:

                        【解决方案19】:

                        只需使用这种方法

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

                        【讨论】:

                          【解决方案20】:

                          将它们直接写入文件。

                          在 Java 中(丑陋):

                          package xxx;
                          class XxxUtils {
                            public static final Yyy xxx(Xxx xxx) { return xxx.xxx(); }
                          }
                          

                          在 Kotlin 中:

                          @file:JvmName("XxxUtils")
                          package xxx
                          fun xxx(xxx: Xxx): Yyy = xxx.xxx()
                          

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

                          【讨论】:

                          • 你忘记了“Kotlin(丑陋)”... KOTLIN: 伴生对象 { val handler = object : Handler(Looper.getMainLooper()) {] ..... JAVA: static Handler handler =新处理程序(Looper.getMainLooper()) {};
                          【解决方案21】:

                          您可以通过 Companion Objects

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

                            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"
                                    }
                            
                                }
                            }
                            

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

                          输出:

                          MyClass.staticField // This is an example of static field Object Decleration
                          
                          MyClass.getStaticFunction() : // This is an example of static function for Object Decleration
                          

                          【讨论】:

                            【解决方案22】:

                            使用@JVMStatic注解

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

                            【讨论】:

                              【解决方案23】:

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

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

                              像使用 java 中的任何静态方法一样使用它:

                              StringUtils.toUpper("foobar")
                              

                              这种模式在 Kotlin 中有点用处,但它的优点之一是它摆脱了对填充静态方法的类的需求。根据您的用例,使用全局、扩展和/或本地函数更合适。在我工作的地方,我们经常在一个单独的平面文件中定义全局扩展函数,命名约定为:[className]Extensions.kt,即 FooExtensions.kt。但更典型的是,我们在操作类或对象中需要它们的地方编写函数。

                              【讨论】:

                                【解决方案24】:

                                让你有一个班级学生。您有一个 static 方法 getUniversityName() 和一个名为 totalStudentstatic 字段。

                                你应该在你的类中声明 companion object 块。

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

                                那么你的班级看起来像

                                    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
                                    }
                                }
                                

                                那么你就可以像这样使用那些静态方法和字段了。

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

                                【讨论】:

                                  【解决方案25】:

                                  kotlin 中没有 static 关键字。如果您想遵循 DRY,kotlin 文档建议使用包级函数。 创建一个带有 .kt 扩展名的文件并将您的方法放入其中。

                                  package p
                                      fun m(){
                                      //fun body
                                      }
                                  

                                  编译后m会有一个public static final void

                                  的签名

                                  import p.m
                                  

                                  【讨论】:

                                    【解决方案26】:

                                    在Java中,我们可以这样写

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

                                    在 Kotlin 中,我们可以这样写

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

                                    伴侣在 Kotlin 中用作静态。

                                    【讨论】:

                                      【解决方案27】:

                                      kotlin 文档提供程序提供三种方式来做到这一点, 第一个是在包中定义函数,没有类:

                                      package com.example
                                      
                                      fun f() = 1
                                      

                                      第二种是使用@JvmStatic注解:

                                      package com.example
                                      
                                      class A{
                                      @JvmStatic
                                      fun f() = 1
                                      }
                                      

                                      第三个是使用伴生对象:

                                      package com.example
                                      
                                      clss A{
                                      companion object{
                                      fun f() = 1
                                      }
                                      }
                                      

                                      【讨论】:

                                        【解决方案28】:

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

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

                                        【讨论】:

                                          【解决方案29】:

                                          如果您需要将函数或属性绑定到一个类而不是它的实例,您可以在伴随对象中声明它:

                                          class Car(val horsepowers: Int) {
                                              companion object Factory {
                                                  val cars = mutableListOf<Car>()
                                          
                                                  fun makeCar(horsepowers: Int): Car {
                                                      val car = Car(horsepowers)
                                                      cars.add(car)
                                                      return car
                                                  }
                                              }
                                          }
                                          

                                          伴生对象是一个单例,其成员可以通过包含类的名称直接访问

                                          val car = Car.makeCar(150)
                                          println(Car.Factory.cars.size)
                                          

                                          【讨论】:

                                          【解决方案30】:

                                          您可以使用Companion Objects - kotlinlang

                                          首先创建该界面可以显示它

                                          interface I<T> {
                                          
                                          }
                                          

                                          然后我们必须在该接口内创建一个函数:

                                          fun SomeFunc(): T
                                          

                                          然后,我们需要一个类:

                                          class SomeClass {}
                                          

                                          在该类中,我们需要该类中的伴随对象:

                                          companion object : I<SomeClass> {}
                                          

                                          在 Companion Object 中,我们需要旧的 SomeFunc 函数,但我们需要覆盖它:

                                          override fun SomeFunc(): SomeClass = SomeClass()
                                          

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

                                          var e:I<SomeClass> = SomeClass()
                                          

                                          【讨论】:

                                            猜你喜欢
                                            • 1970-01-01
                                            • 1970-01-01
                                            • 1970-01-01
                                            • 1970-01-01
                                            • 2016-04-10
                                            • 2017-10-29
                                            • 1970-01-01
                                            • 1970-01-01
                                            相关资源
                                            最近更新 更多