I know this question has been asked before but I haven't been able to solve it yet.
I am trying to create an instance of a class through a generic type.
I've tried this:
Class<VH>::getConstructor.call(parameter).newInstance()
But, I get this error: I get this error for this method: Callable expects 2 arguments, but 1 were provided.
I've also tried this method:
inline fun <reified VH> create(): VH {
return VH::class.java.newInstance()
}
However, I haven't been able to call it because I can't use a generic type as a reified type.
This approach also doesn't work:
fun <VH> generateClass(type: Class<VH>): VH {
return type.newInstance()
}
As when I call it like this: generateClass<VH>(Class<VH>::class.java)
I get this error: Only classes are allowed on the left handside of a class literal
.
My question in a nutshell: How do I create an instance of a class from a generic type?
Thanks in advance
You can't. Unless the generic type is reified it disappears during runtime, making you unable to create an instance.
Your example of the reified function create()
works, but a reified type must be resolved during compilation, so standard generic types cannot be entered as a reified type.
Example of reified "class generating":
inline fun <reified VH : Any> generateClass(): RecyclerView.Adapter {
return object : RecyclerView.Adapter<VH>() {
override fun onBindViewHolder(VH holder, int position) {
// Do implementation...
}
...
}
}
The answer is using reflection and a reified generic type.
Firstly, make sure that the method that takes takes VH as a parameter is an inline function. Once you have a reified version of the generic type you can get its class name.
Once you have its class name you can instantiate it using reflection.
Here's how you get the class's name:
inline fun <reified VH: CustomClass> myMethod() {
//Make sure you use the qualifiedName otherwise the reflective call won't find the class
val className VH::class.qualifiedName!!
}
Here's how you instantiate the class:
Class.forName(className).newInstance(constructorData) as VH
Note: If the class is an inner class then you will get a classnotfoundexception unless you replace the dot before the inner class's name with a $
symbol.
Here's an example:
com.example.package.outerClass.innnerClass
- This will throw the classnotfoundexception
com.example.package.outerClass$innnerClass
- This will successfully find the class
Update:
Another solution that you can use that avoids reflection is using the reified generic type's constructor.
Here's how you get its constructor:
inline fun <reified VH: CustomClass> myMethod() {
val customClassConstructor = VH::class.constructors.first()
}
This is how you instantiate the reified generic type using its constructor:
customClassConstructor.call(constructorData)