'How can I call Kotlin extension function with receiver from the Java static method?

Probably I miss something very simple, but let's imagine I have this extension method in Kotlin:

fun Any.log(message: String) {
    println(this.javaClass.simpleName + message)
}

Is it possible to call it from the static method in Java class?

Note. From the regular instance method, I can do

MyExtensionsKt.log(this, "This is a log message")

But the static method doesn't have an object instance.



Solution 1:[1]

You could just pass a random Object in:

MyExtensionsKt.log(new Object(), "This is a log message");

Of course, this will produce a log message that starts with Object, not the name of the current class.

To produce a log message that starts with the name of the current class, you would need to either create a new, temporary instance of the current class:

// suppose the static method is in "SomeClass"
MyExtensionsKt.log(new SomeClass(), "This is a log message");

or change the implementation of the log method to be a bit smart about its receiver. For example, if it is found that it is a Class, then just directly use its name as the prefix for the log message.

fun Any.log(message: String) {
    val prefix = if (this is Class<*>) {
        this.simpleName
    } else {
        this.javaClass.simpleName
    }
    println(prefix + message)
}

// then in SomeClass, you can do:

MyExtensionsKt.log(SomeClass.class, "This is a log message");

If you cannot do either of those things, then I would suggest that you not use a static method. How about the singleton pattern instead?

Example:

private static final SomeClass INSTANCE = new SomeClass();
public static final SomeClass getInstance() { return INSTANCE; }

// now you can have instance methods, and have access to "this"!

Side note:

Singletons are also how Kotlin's objects are implemented in the JVM.

object Foo {
    fun foo() { 
        this.log("This is a log message")
    }
}

When you call Foo.foo(), it may seem like you are calling a "static" method, but you are really just calling Foo.INSTANCE.foo(). Because of this, this is available in Kotlin objects.

Solution 2:[2]

When you invoke that extension function in Kotlin code, it will look something like:

myObject.log("hello world")

To do the same thing from Java code, you would write:

MyExtensionsKt.log(myObject, "hello world")

The reason the code in your question works in an instance method is that this is a reference to the enclosing object. However, in a static method, there's no enclosing instance, so you'll need to provide some other object reference.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sweeper
Solution 2 Ben P.