Home > Blockchain >  Using reflection on singleton object kotlin?
Using reflection on singleton object kotlin?

Time:04-13

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()
        }
    }
  • Related