Kotlin扩展函数访问Java专用字段
我想在使用Kotlin扩展功能时访问Java的私有字段 假设我有一个Java类Kotlin扩展函数访问Java专用字段,kotlin,kotlin-extension,kotlin-interop,Kotlin,Kotlin Extension,Kotlin Interop,我想在使用Kotlin扩展功能时访问Java的私有字段 假设我有一个Java类ABCABC只有一个专用字段mPrivateField。我想在Kotlin中编写一个扩展函数,无论出于什么原因使用该字段 public class ABC { private int mPrivateField; } Kotlin功能将是: private fun ABC.testExtFunc() { val canIAccess = this.mPrivateField; } 我得到的错误是:
ABC
<代码>ABC只有一个专用字段mPrivateField
。我想在Kotlin中编写一个扩展函数,无论出于什么原因使用该字段
public class ABC {
private int mPrivateField;
}
Kotlin功能将是:
private fun ABC.testExtFunc() {
val canIAccess = this.mPrivateField;
}
我得到的错误是:
无法访问“mPrivateField”:它在“ABC”中是私有的
有没有办法绕过这个限制?这是设计上不可能的。扩展函数本质上分解为静态函数,并将接收器作为其第一个参数。因此,一个扩展函数
fun String.foo() {
println(this)
}
编译为如下内容:
public static void foo(String $receiver) {
System.out.println($receiver);
}
现在可以清楚地看到,您无法访问$receiver
的私有成员,因为它们是私有的
如果您确实想访问该成员,可以使用反射来访问,但您将失去所有保证。正如nhaarman所建议的那样,我使用反射来访问相关字段。具体地说,我创建了一个getter,它在所提到的类(即
ABC
)的内部使用反射
遗憾的是,截至2017年7月,无法访问Kotlin扩展功能中的私有字段
首先,您需要获取并启用一个可在Kotlin中访问的,例如:
val field = ABC::class.java.getDeclaredField("mPrivateField")
field.isAccessible = true
val it: ABC = TODO()
val value = field.getInt(it)
然后,您可以从声明类的实例中将字段值读取为Int
by,例如:
val field = ABC::class.java.getDeclaredField("mPrivateField")
field.isAccessible = true
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;
}
}
使用泛型类型扩展holi java的答案:
使用下面的扩展函数获取私有变量
fun <T : Any> T.getPrivateProperty(variableName: String): Any? {
return javaClass.getDeclaredField(variableName).let { field ->
field.isAccessible = true
return@let field.get(this)
}
}
fun T.getPrivateProperty(variableName:String):有吗?{
返回javaClass.getDeclaredField(variableName).let{field->
field.isAccessible=true
return@let字段。获取(此)
}
}
设置私有变量值获取变量
fun <T : Any> T.setAndReturnPrivateProperty(variableName: String, data: Any): Any? {
return javaClass.getDeclaredField(variableName).let { field ->
field.isAccessible = true
field.set(this, data)
return@let field.get(this)
}
}
fun T.setAndReturnPrivateProperty(variableName:String,data:Any):Any?{
返回javaClass.getDeclaredField(variableName).let{field->
field.isAccessible=true
field.set(此字段,数据)
return@let字段。获取(此)
}
}
获取变量使用:
val bool = <your_class_object>.getPrivateProperty("your_variable") as String
val bool = <your_class_object>.setAndReturnPrivateProperty("your_variable", true) as Boolean
val str = <your_class_object>.setAndReturnPrivateProperty("your_variable", "Hello") as String
val bool=.getPrivateProperty(“您的变量”)作为字符串
设置并获取变量使用:
val bool = <your_class_object>.getPrivateProperty("your_variable") as String
val bool = <your_class_object>.setAndReturnPrivateProperty("your_variable", true) as Boolean
val str = <your_class_object>.setAndReturnPrivateProperty("your_variable", "Hello") as String
val bool=.setAndReturnPrivateProperty(“您的_变量”,true)作为布尔值
val str=.setAndReturnPrivateProperty(“您的_变量”、“您好”)作为字符串
为什么需要访问java私有字段?它来自一个外部编译库,我想扩展它,而不在我的项目中包含整个源代码。库中有用于Android日历事件的“get”方法,我想将“insert Calendar event”功能添加到类中。修改外部库私有字段是危险的。它可能会毁了你的申请。您可以使用java更改字段值。是的,我同意。但我只想得到那个领域。使用它的方法就像我扩展的类一样。这里没有真正的威胁…我希望kotlin的人能够自动生成反射方法,以简化将来的私有字段获取程序。。。虽然我同意在大多数情况下这并不安全,但那是不可能发生的。任何人都不应该鼓励这样的反思。Android平台上的轶事承诺:。在这种情况下,谷歌不得不回滚一个私人成员的重命名,因为Facebook是通过反射访问它的。你可以直接使用Class#getDeclaredField
&Field#getInt
。因为您确切地知道要获取的字段。这是一个以内联方式解决问题的干净解决方案。无需定义单独的扩展getter。Thanks@kosiara-BartoszKosarzycki当然,你可以,如果你愿意,你可以把函数变成内联函数。然而,当您想要使操作抽象时,扩展是必需的,例如:testExtFunc(action:(Int)->R)
,将读取逻辑与操作
逻辑分开,并且您可以在任何地方重用读取函数testExtFunc
。然后您可以将其用作,testExtFunc(foo)
或testExtFunc(bar)
它们就像让/在kotlin中运行/应用和.etc。如何获取具有侦听器类型的字段,如复合按钮中的mOnCheckedChangeListener
?超级!对我有用。谢谢