Kotlin扩展通用函数与基本类型没有反射API

我有一个Java对象具有方法getLonggetBooleangetString 。 我试图做一个通用的扩展函数,它具有作为最后一个参数的功能。 本质上包装的尝试和捕获和调用getString等可能会引发异常。 当我调用getIt<Long>() { // do something with it }我发现<reified T>需要反射api来找出T 我不能做的是检查也不isInstance。 有任何想法吗?

 // This is the non generic function version to get an idea inline fun JSONObject.getItLong(key: String, block: (value: Long) -> Unit) { try { block(this.getLong(key)) } catch (e: JSONException) { Log.w("${ javaClass.simpleName }KEx", e.message) } } 

下面的when不起作用。

 inline fun <reified T> JSONObject.getIt(key: String, block: (value: T) -> Unit) { try { when { Long is T -> { block(this.getLong(key) as T) } String is T -> { block(this.getString(key) as T) } // Boolean is T -> { block(this.getBoolean(key) as T) } // Boolean broken, does not have companion object? } } catch (e: JSONException) { Log.w("fetchFromJSONObject", e.message) } } 

所以,除了布尔问题,我想通过使用T来调用正确类型的get。 我碰到需要将kaitlin反射罐添加到类路径。 如果可能,我想避免这种情况。

UPDATE1:第一个答案和响应使用T::class when ,实际上并没有工作。 感谢这个想法,它帮助我再次看。 第二个我发现比我想要的更“字眼”,所以我结束了这个解决方案。

 inline fun <reified T> JSONObject.getIt(key: String, block: (value: T) -> Unit) { try { block(this.get(key) as T) } catch (e: JSONException) { Log.w("${ javaClass.simpleName }KEx", e.message) } } 

jsonObj.getIt<String>("error", JSONObject::getString) { err = it }相比, jsonObj.getIt<String>("error") { er = it } jsonObj.getIt<String>("error", JSONObject::getString) { err = it }

UPDATE2:这似乎最终是一个更好的方法,至少对我来说,避免与泛型一起工作来实现目标的问题

 inline fun JSONObject.unless(func: JSONObject.() -> Unit) { try { this.func() } catch (e: JSONException) { Log.w("${ javaClass.simpleName }KEx", e.message) } } 

使用:

 jsonObj.unless { sDelay = getLong("s_delay") * 1000 wDelay = getLong("w_delay") * 1000 } jsonObj.unless { sam = getBoolean("sam") } jsonObj.unless { err = getString("error") } 

kotlin is运算符左边is一个对象,右边是一个类的引用。 您可以只使用简单的相等性检查,因为您已经在两边都有类参考。

T在编译时仍然是未知的,所以把this.get*() as T并没有什么意义。 你已经在你的block中验证了类型,所以你可以使用它。

作为一个完整的问题,你可能还想包含一个else块,以防有人调用jsonObject.getIt<Date>(...)

我还包括了第二个版本,需要一个额外的参数来调用,但听起来像你最初想要的不太冗长的版本。 它需要keyaccessorblock ,并且可以在将来添加到JSONObject任何现有的和新的访问器上工作,而不必对扩展名进行修饰或修改。

 inline fun <reified T> JSONObject.getIt(key: String, block: (value: T) -> Unit) { try { when (T::class) { kotlin.Long::class -> block(this.getLong(key) as Long) kotlin.String::class -> block(this.getString(key) as String) kotlin.Boolean::class -> block(this.getBoolean(key) as Boolean) } } catch (e: JSONException) { Log.w("fetchFromJSONObject", e.message) } } inline fun <T> JSONObject.getIt(key: String, accessor: JSONObject.(String) -> T, block: (T) -> Unit) { try { accessor(key).let(block) } catch (e: JSONException) { Log.w("fetchFromJSONObject", e.message) } }