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/WP1j6WzzTTL;DR the lambda
valgets compiled to a Functor class (ExampleKt$test$1) which implementskotlin.jvm.functions.Function0<kotlin.Unit>. An instance of that class gets stored in a private static field of theExampleKtclass, 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@JvmStaticcan't help here since yourval fooalready gets compiled to a static member, but it's a field and not a function.