I have a use case where I need to use reflection to call method of my singleton class
Singleton class is as below
object Singleton {
fun calledFromReflection(){
println("Successfull")
}
}
This is how I am using the reflection
val adsUtiltyCls: Class<*>? = Class.forName("com.xia.Singleton")
val adsUtilityObj: Any? = adsUtiltyCls?.newInstance()
if (adsUtilityObj != null) {
val method: Method
try {
method = adsUtiltyCls.getDeclaredMethod("calledFromReflection")
val value=method.invoke(adsUtilityObj)
println("value $value")
} catch (e: Exception) {
e.printStackTrace()
}
}
I get the following error
java.lang.IllegalAccessException: void com.com.xia.Singleton.<init>() is not accessible from java.lang.Class<com.xia.RetargetActivity>
CodePudding user response:
The problem is that you try to create an instance of your Singleton
object which already is an instance and does not have a public constructor.
In order to access the object instance you have to change your object adsUtilityObj
to be the object instance of the corresponding Kotlin-class:
val adsUtilityObj = adsUtiltyCls?.kotlin.objectInstance
Moreover, you could use Kotlin Reflection instead of pure Java reflection. Then you can write:
val clazz = Class.forName("com.xia.Singleton").kotlin
clazz.functions.find { it.name == "calledFromReflection" }?.call(clazz.objectInstance)
or equivalently
Singleton::class.functions.find { it.name == "calledFromReflection" }?.call(Singleton)
CodePudding user response:
I was able to do it with the below. Kotlin singleton Object
has field named INSTANCE
and also a private constructor
val adsUtiltyCls: Class<*>? = Class.forName("com.xia.Singleton")
val instance: Field = adsUtiltyCls!!.getDeclaredField("INSTANCE")
instance.isAccessible = true
val constructor = adsUtiltyCls.getDeclaredConstructor()
constructor.isAccessible = true
val adsUtilityObj: Any? = constructor?.newInstance()
if (adsUtilityObj != null) {
val method: Method
try {
method = adsUtiltyCls.getDeclaredMethod("calledFromReflection")
val value=method.invoke(adsUtilityObj)
println("value $value")
} catch (e: Exception) {
e.printStackTrace()
}
}