Kotlin扩展功能访问Java专用字段
在使用Kotlin 扩展功能时,我想访问Java的专用字段 。
假设我有一个Java类ABC
。 ABC
只有一个私人字段mPrivateField
。 我想在Kotlin中写一个扩展函数,无论出于什么原因都使用这个字段。
public class ABC { private int mPrivateField; }
Kotlin函数将是:
private fun ABC.testExtFunc() { val canIAccess = this.mPrivateField; }
我得到的错误是:
Cannot access 'mPrivateField': It is private in 'ABC'
任何方式来解决这个限制?
首先,您需要获得一个字段并使其可以在Kotlin中访问 ,例如:
val field = ABC::class.java.getDeclaredField("mPrivateField") field.isAccessible = true
然后,您可以从声明类的实例中通过Field#getInt将字段值读为Int
,例如:
val it: ABC = TODO() val value = field.getInt(it)
最后,你的扩展方法如下所示:
private inline fun ABC.testExtFunc():Int { return javaClass.getDeclaredField("mPrivateField").let { it.isAccessible = true val value = it.getInt(this) //todo return@let value; } }
这是不可能的设计。 扩展函数本质上是以接收者作为第一个参数的静态函数。 因此,一个扩展功能
fun String.foo() { println(this) }
编译成如下所示:
public static void foo(String $receiver) { System.out.println($receiver); }
现在很明显看到你不能访问$receiver
私人成员,因为他们是私人的。
如果你真的想访问该成员,你可以使用反射,但你会失去所有的保证。
就像nhaarman建议我用反射进入有问题的领域。 具体来说,我创建了一个getter,它在所提到的类(即ABC
)内部使用了反射,
Kotlin扩展功能中的私人字段可能会在2017年7月份之前无法使用
fun ABC.testExtFunc() { val canIAccess = this.getmPrivateField() } fun ABC.getmPrivateField() : Int { val field = this.javaClass.declaredFields .toList().filter { it.name == "mPrivateField" }.first() field.isAccessible = true val value = field.get(this) return value as Int }