What is the equivalent of Java static methods in Kotlin?

前端 未结 28 943
眼角桃花
眼角桃花 2020-11-27 09:03

There is no static keyword in Kotlin.

What is the best way to represent a static Java method in Kotlin?

相关标签:
28条回答
  • 2020-11-27 09:38

    A lot of people mention companion objects, which is correct. But, just so you know, you can also use any sort of object (using the object keyword, not class) i.e.,

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

    Use it just like any static method in java:

    StringUtils.toUpper("foobar")
    

    That sort of pattern is kind of useless in Kotlin though, one of its strengths is that it gets rid of the need for classes filled with static methods. It is more appropriate to utilize global, extension and/or local functions instead, depending on your use case. Where I work we often define global extension functions in a separate, flat file with the naming convention: [className]Extensions.kt i.e., FooExtensions.kt. But more typically we write functions where they are needed inside their operating class or object.

    0 讨论(0)
  • 2020-11-27 09:39

    Use object to represent val/var/method to make static. You can use object instead of singleton class also. You can use companion if you wanted to make static inside of a class

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

    If you need to call it from Java:

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

    In Kotlin, ignore INSTANCE.

    0 讨论(0)
  • 2020-11-27 09:39

    The exact conversion of the java static method to kotlin equivalent would be like this. e.g. Here the util class has one static method which would be equivalent in both java and kotlin. The use of @JvmStatic is important.

    Java code:

        class Util{
             public static String capitalize(String text){
             return text.toUpperCase();}
           }
    

    Kotlin code:

        class Util {
            companion object {
                @JvmStatic
                fun capitalize(text:String): String {
                    return text.toUpperCase()
                }
            }
        }
    
    0 讨论(0)
  • 2020-11-27 09:40

    Even though this is a bit over 2 years old now, and had plenty of great answers, I am seeing some other ways of getting "static" Kotlin fields are missing. Here is an example guide for Kotlin-Java static interop:

    Scenario 1: Creating a static method in Kotlin for Java

    Kotlin

    @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's answer provides more depth than this, and should definitely be referenced for this scenario.


    This next scenario handles creating static fields in Kotlin so that Java doesn't have to keep calling KotlinClass.foo() for those cases where you don't want a static function.

    Scenario 2: Creating a static variable in Kotlin for Java

    Kotlin

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

    One of the great features about Kotlin is that you can create top level functions and variables. This makes it greate to create "classless" lists of constant fields and functions, which in turn can be used as static functions/fields in Java.

    Scenario 3: Accessing top level fields and functions in Kotlin from 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);
        }
    }
    

    Another notable mention that can be used in Java as "static" fields are Kotlin object classes. These are zero parameter singleton classes that are instantiated lazily on first use. More information about them can be found here: https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations

    However, to access the singleton, a special INSTANCE object is created, which is just as cumbersome to deal with as Companion is. Here's how to use annotations to give it that clean static feel in Java:

    Scenario 4: Using object classes

    Kotlin

    @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);
        }
    }
    
    0 讨论(0)
  • 2020-11-27 09:40

    For Android using a string from a single activity to all the necessary activity. Just like static in java

    public final static String TEA_NAME = "TEA_NAME";

    Equivalent approach in 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)
        }
    }
    

    Another activity where value is needed:

    val teaName = MainActivity.TEA_NAME
    
    0 讨论(0)
  • 2020-11-27 09:40

    Let, you have a class Student. And you have one static method getUniversityName() & one static field called totalStudent.

    You should declare companion object block inside your class.

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

    Then your class looks like

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

    Then you can use those static method and fields like this way.

    println("University : " + Student.getUniversityName() + ", Total Student: " + Student.totalStudent)
        // Output:
        // University : MBSTU, Total Student: 30
    
    0 讨论(0)
提交回复
热议问题