Kotlin扩展功能访问Java私有字段
我想访问Java的私有字段使用Kotlin 扩展功能。Kotlin扩展功能访问Java私有字段
假设我有一个Java类ABC
。 ABC
只有一个私人字段mPrivateField
。我想在Kotlin中写一个扩展函数,无论出于什么原因都使用该字段。
public class ABC {
private int mPrivateField;
}
的科特林功能是:
private fun ABC.testExtFunc() {
val canIAccess = this.mPrivateField;
}
我得到的错误是:
Cannot access 'mPrivateField': It is private in 'ABC'
的任何方式让周围这种限制?
首先吸气,你需要以获得Field并启用它可以在科特林访问,例如:
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
[email protected] value;
}
}
这是一个干净的解决方案,它以**内联**方式解决问题。无需定义单独的扩展吸气剂。谢谢 –
@ kosiara-BartoszKosarzycki当然,如果你喜欢,你可以将函数变成**内联函数。 Howerver,当你想要抽象操作时,扩展是必须的,例如:'testExtFunc(action:(Int) - > R)',将读取逻辑与'action'逻辑分开,并且可以重新使用读取函数'testExtFunc'任何地方。那么你可以使用它作为'testExtFunc(foo)'或'testExtFunc(bar)'它们就像在''''''''''''''''应用'和'.etc在kotlin中一样。 –
这是不可能的设计。扩展函数基本上解析为接收器作为其第一个参数的静态函数。因此,扩展功能
fun String.foo() {
println(this)
}
编译成类似:
public static void foo(String $receiver) {
System.out.println($receiver);
}
现在很清楚的看到你不能访问的$receiver
私有成员,因为他们是,那么,私人。
如果你真的想要访问该成员,你可以使用反射,但你会失去所有保证。
就像nhaarman建议我用反射来访问有问题的字段。具体来说,我创建了用于反射内部中提到的类(即ABC
)
可悲的是访问在科特林扩展功能的私人领域,是不可能的,因为的2017年七月
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
}
你可以直接使用'Class#getDeclaredField'和'Field#getInt'。因为你确切知道你想要获得什么领域。 –
你为什么要需要访问java ** private **字段? –
它来自一个外部编译库,我希望在不包括整个源代码的情况下扩展到我的项目中。该库具有Android日历事件的“获取”方法,我希望将“插入日历事件”功能添加到类中。 –
修改外部库**私人**字段是*危险*。它可能会粉碎你的应用程序。您可以使用java [反射](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/package-summary.html)更改字段值。 –