given following Kotlin class:
class Foo { public fun bar(i: Int = 0): Int = 2 * i }
How should I call 'bar' function without any parameter from a java/groovy code?
def f = new Foo() f.bar() //throws: java.lang.IllegalArgumentException: Parameter specified as non-null contains null
Kotlin Default Argument In Kotlin, you can provide default values to parameters in function definition. If the function is called with arguments passed, those arguments are used as parameters. However, if the function is called without passing argument(s), default arguments are used.
Kotlin functions are first-class, which means they can be stored in variables and data structures, and can be passed as arguments to and returned from other higher-order functions. You can perform any operations on functions that are possible for other non-function values.
I know unit is the default return type in kotlin.
You can do this now in Kotlin. For your class method, use the @JvmOverloads
annotation.
class Foo { @JvmOverloads public fun bar(name: String = "World"): String = "Hello $name!" }
Now simply call it from Java:
Foo foo = new Foo(); System.out.println(foo.bar()); System.out.println(foo.bar("Frank"));
Outputs the following:
Hello World!
Hello Frank!
I'll post the real answer shortly, but if anyone is wanting to do this from reflection, here is how the code would look. Much more complicated, but educational about how to use Kotlin reflection for KCallable
.
Here is the class to call:
class Foo { public fun bar(name: String = "World"): String = "Hello $name!" }
Then we need a utility class in Kotin that can receive an instance of a class, a method from java reflection, and the parameters by name. This only works with non-primitives:
class KReflectHelper { companion object { @Suppress("UNCHECKED_CAST") @JvmStatic fun <T> callKotlinMethodWithNamedParms(instance: Any, method: Method, parmMap: Map<String, Any>): T { val callable: KFunction<T> = method.kotlinFunction as? KFunction<T> ?: throw IllegalStateException("Method is not a Kotlin method") val unusedParms = HashSet(parmMap.keys) val callableParms = hashMapOf<KParameter, Any?>() callable.parameters.map { parm -> if (parm.kind == KParameter.Kind.INSTANCE) { callableParms.put(parm, instance) } else if (parm.kind == KParameter.Kind.VALUE && parmMap.contains(parm.name)) { unusedParms.remove(parm.name) callableParms.put(parm, parmMap.get(parm.name)) } else if (parm.kind == KParameter.Kind.VALUE) { if (parm.isOptional) { // default value will be used! } else { throw IllegalStateException("Missing required parameter ${parm.name}") } } else { throw IllegalStateException("Cannot call methods that are not direct instance methods") } } if (unusedParms.isNotEmpty()) { throw IllegalStateException("Unrecognized parameters passed to function: $unusedParms") } return method.kotlinFunction?.callBy(callableParms) as T } } }
Now that static method can be called from Java, but it isn't so much fun. A code generator would really be required. Calling it from Kotlin is much easier and some frameworks (such as Klutter and Kovert) already use something along these lines.
Foo foo = new Foo(); System.out.println(foo.bar("Frank")); Method barMethod = Foo.class.getMethod("bar", String.class); Map<String, Object> parms = new HashMap<String, Object>(); parms.put("name", "David"); System.out.println(KReflectHelper.callKotlinMethodWithNamedParms(foo, barMethod, parms)); // now call using the default parms.clear(); System.out.println(KReflectHelper.callKotlinMethodWithNamedParms(foo, barMethod, parms));
Ouput:
Hello Frank!
Hello David!
Hello World!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With