Equivalent of Java static methods and fields in Kotlin

Like to share

1. Overview

In this article, we will explain the Object declaration (old Java way) and package-level (new kotlin way) functions which are the equivalent of Java static methods and fields in Kotlin. As we all knew, Kotlin doesn’t have the static keyword.

2. Object Declaration for static members

class is a template, and an object is an instance of a class. Usually, you define a class and then create multiple instances of that class wherever required. If you want to restrict the instantiation of an object to a single instance, then you can use the Object keyword in Kotlin to achieve a singleton object. It is equivalent to Java’s singleton pattern.

An object declaration is a singleton object that can be useful in several cases. This always results in a single instance even if two threads try to instantiate it. This makes it easier for us to declare the Singleton pattern in Kotlin. It is also like the static methods in Java.

object SingletonObject {                                                 
    fun validateCredentials(username: String, password: String) {        
        // Code to validate credentials
        println("Validation completed")
    }
}
fun main() {
   SingletonObject.validateCredentials("John", "John123")
}

You can force to generate the members of companion objects as real static methods and fields using @JvmStatic annotation. You can use @JvmField for static fields.

object SingletonObject {    
    @JvmField
    val TAG = "SingletonObject"             
    @JvmStatic                                
    fun validateCredentials(username: String, password: String) {        
        // Code to validate credentials
        println("Validation completed")
    }
}
fun main() {
   SingletonObject.validateCredentials("John", "John123")
}

If you want to create a singleton object inside a class, then use the Companion object.

2.1 Companion Object

A companion object is a standalone object of the class that is an object declaration inside the class. If you want the class to access the private members of the singleton object, then you can use the Companion object.

If you need to call a function without using a class instance, then you can use the Companion object. Syntactically it is like the static methods in Java and you can access the companion object members using its class name as a qualifier.

class ExampleClass {
    val username = "John"
    companion object Named {
        fun create(): ExampleClass = ExampleClass()
    }
}
fun main() {
    val instance = ExampleClass.create()    
    println(instance.username)
}

In the above example, we are calling the create function of the companion object using its class name ExampleClass.

The name of the class used by itself acts as a reference to the companion object of the class. So here, ExampleClass indeed refers to the companion object. Also ExampleClass instance members can access the private members of the Companion object.

If you debug the code, you would see the ExampleClass refers to companion object which is a singleton object.

The name of the companion object is optional so you can omit it if you don’t want it.

class ExampleClass {
    val username = "John"
    companion object {
        fun create(): ExampleClass = ExampleClass()
    }
}
fun main() {
    val instance = ExampleClass.create()    
    println(instance.username)
}

But you would call it in Java as below. The syntax is ClassName.CompanionObjectName.functionName (ExampleClass.CompanionName.create).

class Caller {
   private String TAG = "Caller";
   private String getUserName() {
       return ExampleClass.Named.create();
   }
}

If you don’t have any name for the companion object, then you would use ExampleClass.Companion.create

class Caller {
   private String TAG = "Caller";
   private String getUserName() {
       return ExampleClass.Companion.create();
   }
}

2.1.1 Force Static using @JvmStatic

However, on the JVM you can force to generate the members of companion objects as real static methods and fields using @JvmStatic annotation.

class ExampleClass {
    val username = "John"
    companion object CompanionName {
        @JvmField 
        val TAG = "CompanionName"
        @JvmStatic
        fun create(): ExampleClass = ExampleClass()
    }
}

2.1.2. Declare static variable in Kotlin

You can declare variables inside the Companion object or object declaration. Though you can access the variable using the class name, it is still a member of a singleton instance, and you can use @JvmField to force it real static fields.

class ExampleClass {
    companion object CompanionName {
        @JvmField 
        val TAG = "CompanionName"
    }
}

2.1.3. Passing Companion Object as a parameter.

You can pass the companion object as an argument to other methods as shown below.

    fun main() {
        printUserName(ExampleClass)
    }
    fun printUserName(value: ExampleClass.CompanionName) {
        println(value.create().username)
    }
class ExampleClass {
    val username = "John"
    companion object CompanionName {
        @JvmStatic
        fun create(): ExampleClass = ExampleClass()
    }
}

3. package-level functions

It’s recommended to use package-level functions also known as top-level functions. You can declare functions and fields directly inside a file creating no class for them. They are often utility functions independent of any class.

Let’s take the same example.

    package com.tedblob
    fun validateCredentials(username: String, password: String) {        
        // Code to validate credentials
        println("Validation completed")
    }
    fun main() {
        validateCredentials("John", "John123")
    }

In this example, we declared the validateCredentials static function outside any class and kept it directly as a top-level function.

4. Call java static method from kotlin

Static members of Java classes can be called using its class name followed by the member name just like in Java.

public class Student {
    public static String getStudentName() {
        return "Britto";
    }
}
fun main() {
   println(Student.getStudentName())
}
Java class as a parameter
Java class as parameter

Companion object can be passed as a parameter to function as mentioned in section 2.1.3 of this article, but we cannot pass this Student as a parameter to any function.

5. Conclusion

In this article, we have learned the equivalent of Java static methods and members in Kotlin. You can still refer to Kotlin docs for more insights.

If you would like to learn more on Kotlin, we recommend you to refer to our Kotlin articles.

Leave a Reply

Your email address will not be published. Required fields are marked *