Search code examples
javaandroidreflectionkotlingetconstructor

How to instantiate an inner class with reflection?


I would like to get the Constructor of a nested class so that I can instantiate it. I want this to be an inner class so that I can access variables from its outer class.

The code below throws a NoSuchMethodException with the inner prefix added:

package com.example

import android.util.Log

class ClassA {

    var iWantToUseThisFromTheInnerClass = "someValue"

    fun runThisToStart() {
        val classB = ClassB(InnerClassA::class.java)
        classB.doSomething()

    }

    inner class InnerClassA(text: String) {
        init {
            Log.d("InnerClassA", "Constructor invoked " + text)
        }
    }

}

package com.example

import java.lang.reflect.InvocationTargetException

class ClassB<T>(private var mModelClass: Class<T>) {

    val someText = "whatever"

    fun doSomething():T {
        try {
            val constructor = mModelClass.getConstructor(String::class.java)
            return constructor.newInstance(someText)
        } catch (e: NoSuchMethodException) {   // Throws this exception
            throw RuntimeException(e)
        } catch (e: InvocationTargetException) {
            throw RuntimeException(e)
        } catch (e: InstantiationException) {
            throw RuntimeException(e)
        } catch (e: IllegalAccessException) {
            throw RuntimeException(e)
        }
    }

}

Thanks


Solution

  • You need to include enclosing classes (ClassA) instance in the constructor as well, since InnerClassA cannot exist without it:

    class ClassA {
    
        var iWantToUseThisFromTheInnerClass = "someValue"
    
        fun runThisToStart() {
            val classB = ClassB(InnerClassA::class.java)
            classB.doSomething(this)
    
        }
    
        inner class InnerClassA(text: String) {
            init {
             //   Log.d("InnerClassA", "Constructor invoked " + text)
            }
        }
    
    }
    
    class ClassB<T>(private var mModelClass: Class<T>) {
    
        val someText = "whatever"
    
        fun doSomething(enclosingObj : Any):T {
                val constructor = mModelClass.getConstructor(enclosingObj::class.java, String::class.java)
                return constructor.newInstance(enclosingObj, someText)
        }
    
    }