A top-level val
with a function type can be used like a "static" function from Kotlin, but is there a way to use it like a static function from Java as well?
For example, say we have a file called Example.kt
that contains absolutely nothing besides this
val foo: (String) -> String = { s -> "Hello, $s" }
Using this in other Kotlin code works as you would expect in any functional language
foo("world")
Conceptually, this definition of foo
is no different than the following Java code:
public class ExampleKt {
public static String foo(String s) {
return "Hello, " + s;
}
}
However, if you actually have to call it from Java, it's pretty janky:
ExampleKt.getFoo().invoke("world")
Desired behavior would be similar to how it can be used in Kotlin, like
import static ExampleKt.foo;
foo("world");
In various other parts of the language, we can use @JvmStatic
to make calling "static" kotlin code less janky from Java. Is there a way to do it here?
Although Kotlin generally does a great job at masking what's going on behind the scenes, a lambda is not the same as a function in the JVM bytecode. It's true that conceptually, there's not many differences because Kotlin really leans into the whole "functions as first-class citizens" thing, but that's mostly just syntactic sugar.
For example, compare the bytecode output of an actual top-level function: https://godbolt.org/z/T7KK11ev7
and the bytecode of a top-level lambda val
: https://godbolt.org/z/WP1j6WzzT
TL;DR the lambda val
gets compiled to a Functor class (ExampleKt$test$1
) which implements kotlin.jvm.functions.Function0<kotlin.Unit>
. An instance of that class gets stored in a private static field of the ExampleKt
class, with a corresponding static getter.
The compilation output is very reminiscent of how Java handles lambdas: They are essentially classes implementing a functional interface (like Function
, Consumer
, Supplier
, ...), and everything else is syntactic sugar. It's just that Kotlin goes one step further and you can use function types instead of functional interfaces.
So I guess the answer to your question is no, there's no way to make this lambda seem like a static function in Java, unless you actually declare it as a fun
. And @JvmStatic
can't help here since your val foo
already gets compiled to a static member, but it's a field and not a function.