Default kotlin function argument parameters from java

defined by the following Kotlin class:

class Foo { public fun bar(i: Int = 0): Int = 2 * i } 

How can I call the function "bar" without any parameter from java / groovy code?

 def f = new Foo() f.bar() //throws: java.lang.IllegalArgumentException: Parameter specified as non-null contains null 
+6
source share
2 answers

You can do it now in Kotlin. For the class method, use the @JvmOverloads annotation .

 class Foo { @JvmOverloads public fun bar(name: String = "World"): String = "Hello $name!" } 

Now just call it from Java:

 Foo foo = new Foo(); System.out.println(foo.bar()); System.out.println(foo.bar("Frank")); 

Outputs the following:

Hello World!

Hi Frank!

+12
source

I will send a real answer soon, but if someone wants to do this out of thought, this is how the code will look. Much more complicated, but a lesson on 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, which can get an instance of the class, a method from java reflection and 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 the static method can be called with Java, but it's not so much fun. Actually a code generator is needed. Calling him from Kotlin is much simpler, and some frameworks (such as Clatter and Covert) already use something in this direction.

  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:

Hi Frank!

Hello David!

Hello World!

+1
source

Source: https://habr.com/ru/post/948243/


All Articles