Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Kotlin: Static Methods

DZone's Guide to

Kotlin: Static Methods

Want to bring static methods to Kotlin? Well, you can't. Not like in Java at least. But here's how to get the same functionality with Kotlin.

· Java Zone ·
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

If you come from the Java world, you are already familiar with static methods. They prevent us from copying our methods to every class and allow us to use them without creating an object. But what if I told you that we don’t have static methods in Kotlin?

It's true. But that doesn’t mean that we can’t reap the benefits provided by static methods in Kotlin. There is a way around them. Let’s see how.

The documentation of Kotlin recommends that you should use package-level functions if you want to follow DRY. This might seem a little odd if you have worked with Java because it’s not there in Java! Let’s create a package-level function in Kotlin. All you need to do is create a file with the .kt extension and put in a method that you’ll be using in multiple places. I’ll be creating a file named SampleClass.kt. The content of SampleClass.kt is:

package packageA
fun bar(){
    println("Method bar")
}


As you can see, we didn’t have to put our bar() method under some top-level class declaration. If you look at the decompiled code, it looks like below:

public final class SameClassKt {
    public static final void bar() {
        String var0 = "Method bar";
        System.out.println(var0);
    }
}


Even though we didn’t put it under any class declaration, Kotlin, upon compilation, will create a class with the name SampleClassKt and will place the method inside it. And notice what the signature of our method is: public static final void bar() Exactly what we wanted to have!

If you want to call this function from any other class, let’s say HelloWorld.kt, you can call it by doing:

package packageB
import packageA.bar
fun main(args: Array < String > ) {
    bar()
}


Notice that we have to import that method from its package, hence the import packageA.bar statement.

Another way to do this is by putting the method in object declaration.

package packageA
object Foo{    
    fun bar() = println("Method bar")    
    var foo="foo"
}


And you can access it like:

Foo.bar()


Object declaration is mostly used inside a class. It is useful if you want to access the internals of a class. To understand it better, let’s see its decompiled code:

public final class Foo {
    public static final Foo INSTANCE;
    public final void bar() {
        String var1 = "Method bar";
        System.out.println(var1);
    }
    private Foo() {
        INSTANCE = (Foo) this;
    }
    static {
        new Foo();
    }
}


Any methods or variables under object declaration will work as static methods or variables.

If you look in the above code, we have a static block that will be executed when the class is loaded into memory. This block is creating the Foo object. Notice that the constructor is private, so the object can only be created from inside the class. Ring a bell? This way, we are getting a Singleton class!

But, if you want to do it just like the old style Java, i.e. by using the class name as a qualifier, you need a Companion identifier.

class SampleClass {
    companion object {
        fun bar() = print("Bar method")
    }
}


And then, you can access it from Kotlin code using the same syntax as used in Java, i.e.:

SampleClass.foo()


One thing to note is that if you call the method under a Companion object from Java code, you’ll need to place the companion identifier between the class name and method name, e.g.:

SampleClass.Companion.foo();


If you don’t like to place companion identifiers in between, you can also give a name to your object:

companion object Foo{
    fun foo()= print("In foo method")
}


And then call it with SampleClass.Foo.foo().

If you want to get rid of your Companion identifier, and also don’t want to give any name to your object, you need to place the @JvmStatic annotation with the method name.

class SampleClass {
    companion object {
        @JvmStatic
        fun foo() = print("In foo method")
    }
}


Then you can call it like SampleClass.foo() from Java code as well.

Before we close this topic, let’s see how to resolve extension functions statically. If you aren’t familiar with extension functions, simply put, they are methods defined outside the class that behave as if they are member functions. Check out the following example:

fun main(args: Array < String > ) {
    val sampleClass = SampleClass()
    sampleClass.foo()
}
class SampleClass {}
private fun SampleClass.foo() {
    println("saas")
}


As you can see, we accessed the foo() method as if it was a part of SampleClass.

Anyways, now we will try to access the extension functions statically. To do so, we need to put an empty companion object inside the class. 

class SampleClass{    
    companion object
}


To define an extension function that can be called statically, we need to put the Companion identifier between the receiver class and method name:

private fun SampleClass.Companion.foo() {
    println("saas")
}


Now, we can call the extension function without creating an object of the receiver class:

SampleClass.foo()


If you look at the decompiled code, it’s pretty much what we wanted:

private static final void foo(@NotNull SampleClass.Companion $receiver) {
    String var1 = "saas";   
    System.out.println(var1);
}


That’s it for today folks! I am writing a book on Kotlin, so follow me to get updated about the things we can achieve with Kotlin. If this post helped you, please tweet it.

Helpful Links

  • Documentation of Kotlin: Classes and Inheritance - Kotlin Programming LanguageKotlin is a statically typed programming language for the JVM, Android and the browser, 100% interoperable with Java.

  • JetBrains team discussing static constants in Kotlin: "Static constants" in KotlinKotlin is designed so that there's no such thing as a "static member" in a class. If you have a function in a class...

  • Great thread by abreslav on resolving extension function statically: How do extension functions work? Just curious: How do extension functions work in Kotlin? This is not about the syntax but about what is going on...

Download Building Reactive Microservices in Java: Asynchronous and Event-Based Application Design. Brought to you in partnership with Red Hat

Topics:
java ,kotlin ,static methods ,tutorial ,companion objects

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}