来自java的kotlin函数默认参数
给予以下Kotlin类:
class Foo { public fun bar(i: Int = 0): Int = 2 * i }
我应该如何调用没有任何参数从一个Java / Groovy代码的“酒吧”功能?
def f = new Foo() f.bar() //throws: java.lang.IllegalArgumentException: Parameter specified as non-null contains null
你现在可以在Kotlin做到这一点。 对于你的类方法,使用@JvmOverloads
注解 。
class Foo { @JvmOverloads public fun bar(name: String = "World"): String = "Hello $name!" }
现在简单地从Java调用它:
Foo foo = new Foo(); System.out.println(foo.bar()); System.out.println(foo.bar("Frank"));
输出以下内容:
你好,世界!
你好弗兰克!
我很快就会发布真正的答案,但如果有人想要从反思中做到这一点,这里是代码的外观。 更复杂的是,如何使用Kotlin反射KCallable
。
这是要调用的类:
class Foo { public fun bar(name: String = "World"): String = "Hello $name!" }
然后我们需要一个Kotin中的实用类,它可以接收一个类的实例,一个来自java反射的方法,以及通过名字的参数。 这只适用于非基元:
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 } } }
现在,可以从Java调用静态方法,但没有那么多乐趣。 代码生成器真的是必需的。 从Kotlin调用它更容易,一些框架(如Klutter和Kovert)已经沿用这些方法。
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));
输出继电器:
你好弗兰克!
大卫你好!
你好,世界!
- Kotlin的访问修饰符是否和Java中的一样?
- Kotlin在GridLayout单元格的底部显示一个边框
- 如何扩展Kotlin Number类或使用泛型来创建一个简单的属性getter,它将在所有的Number子类上运行?
- 如何使用Lamba表达式使Java方法调用在Kotlin中不那么冗长?
- Kotlin:通过实现一个接口作为参数
- Android中的Kotlin协程:为什么要使用Anko中的bg()而不是async()?
- 禁止使用方法或类的“使用属性访问语法”
- kotlin:注释中数组的一些问题
- Android / Kotlin崩溃在开始4.1.2 – ExceptionInInitializerError