What Is the Equivalent of Java Static Methods in Kotlin

What is the equivalent of Java static methods in Kotlin?

You place the function in the "companion object".

So the java code like this:

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

will become

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

You can then use it from inside Kotlin code as

Foo.a();

But from within Java code, you would need to call it as

Foo.Companion.a();

(Which also works from within Kotlin.)

If you don't like having to specify the Companion bit you can either add a @JvmStatic annotation or name your companion class.

From the docs:

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.

Adding the @JvmStatic annotation looks like this

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

and then it will exist as a real Java static function, accessible from
both Java and Kotlin as Foo.a().

If it is just disliked for the Companion name, then you can also
provide an explicit name for the companion object looks like this:

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

which will let you call it from Kotlin in the same way, but
from java like Foo.Blah.a() (which will also work in Kotlin).

How do you make Kotlin static variables and functions for Java?

You can't. Well, at least in a pure Kotlin project.

Kotlin has no notion of static. The way static works in a Kotlin-Java project is by use of annotations on the Kotlin classes to tell the JVM that the desired variable/function should be exposed as a static to Java classes.

The following is an example guide for Kotlin-Java static interop (answer originally posted in What is the equivalent of Java static methods in Kotlin?):

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

This 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

// There is no more need for the @file:JvmName() annotation. The object class below already handles the proper naming.

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

Alternative way for kotlin static methods

One way to do this is by making the class open or abstract and adding this

companion object Default: Test()

This makes it act like every method of Test() is inside the companion object Default.
If you wanted, you could also override an open method and make it have a different output for when it is used statically:

fun main() {
val test = Test()
test.foo() //Output: "jiorgor"
Test.foo() //Output: "static jiorgor"
}

public open class Test() {

var giorgor: String = "jiorgor"

open fun foo() = println(giorgor)
companion object Default : Test() {
override fun foo() = println("static jiorgor")
}
}

Kotlin static methods and variables

The closest thing to Java's static fields is a companion object. You can find the documentation reference for them here: https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects

Your code in Kotlin would look something like this:

class Foo {

companion object {
lateinit var instance: Foo
}

init {
instance = this
}

}

If you want your fields/methods to be exposed as static to Java callers, you can apply the @JvmStatic annotation:

class Foo {

companion object {
@JvmStatic lateinit var instance: Foo
}

init {
instance = this
}

}

Static methods in Kotlin as static method in Java

Works for me this way:

class C {
companion object {
@JvmStatic
fun foo(): Boolean = true
}
}

val method = C::class.java.getDeclaredMethod("foo")

Modifier.isStatic(method.modifiers) // true

Note that C::class.java and C.javaClass are different things: the former returns Class<C> and the latter returns Class<C.Companion>.

How to create static functions in Kotlin without creating an object

Unfortunately, there's currently no way to create a static function on a class in Kotlin that doesn't result in the instantiation of an Object (the companion object). You'll have to write it in Java and call it from Kotlin if you want to do this.

The @JvmStatic annotation creates a static method in the JVM bytecode, but all that does is retrieve the instance of the companion object and call the method on it, which you can verify by decompiling the resulting bytecode.

use static Java methods as static (or singleton) properties in Kotlin

Having read the answers of the experts, having studied the links they provided, and having decompiled the Kotlin code of the wrapper class and analyzed a demo app (pure Java) which used the Kotlin-wrapped library, I decided to change the Java API.

Now I have a class with a public static object:

public class MyDevice { 
public static MyDevice myDevice;
public void setLocation(Location location) {…}
public Location getLocation() {…}
}

now the Java consumers will use

import static com.example.sdk.MyDevice.myDevice;

Kotlin consumers don't need that static:

import com.example.sdk.MyDevice.myDevice

So, I don't need a separate Kotlin flavor of my library!

Possibility to call a Java static method in Kotlin

Yes, you can.
Java code:

public class MyJavaClass {
public static void printFoo() {
System.out.println("foo");
}
}

Kotlin code:

fun main(args: Array<String>) {
MyJavaClass.printFoo()
}

So easy =)

How to make static methods in Kotlin

In your java version the appComponent is static too. Might want to move appComponent to the companion object in the Kotlin version to make it static too.



Related Topics



Leave a reply



Submit