On the problem of instantiating classes in Kotlin reflection

start with java code:


public class TUtil {
    public static <T> T getT(Object o, int i) {
        try {
            return ((Class<T>) ((ParameterizedType) (o.getClass()
                    .getGenericSuperclass())).getActualTypeArguments()[i])
                    .newInstance();
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
        } catch (ClassCastException e) {
        }
        return null;
    }
}

//:
public abstract class BaseMVPActivity<T extends BasePresenter, E extends BaseModel>

mPresenter = TUtil.getT(this, 0);
mModel = TUtil.getT(this, 1);

I try to use kotlin to write this util class:


class KClassUtil {
    companion object {
        inline fun <reified T> getKType(K: Any,position:Int):T {
            var parameterizedType = K::class.java.genericSuperclass as ParameterizedType
            var actualTypeArguments = parameterizedType.actualTypeArguments
            return ( actualTypeArguments[position].javaClass as Class<T>).newInstance()
        }
    }
}

//:
abstract class BaseMVPActivity<T : BasePresenter<*, *>, E : BaseModel> : BaseActivity()

mPresenter = KClassUtil.getKType(this, 0)   //
mModel = KClassUtil.getKType(this, 1)       //
Cannot use "T" as reified type parameter. Use a class instead.

I must write a concrete Class in the kotlin here, but since this is an abstract class, I can"t know what the concrete class is. How can I solve this problem?

May.30,2022

you cannot get the class of this generic T. The correct way to get it is to declare an abstract protected variable in BaseMVPActivity, which is implemented by the concrete activity, such as
protected abstract val presenterClassToken: Class < T >
. Then, when the concrete activity inherits the BaseMVPActivity, implement this variable. XXXPresenter refers to the concrete presenter implementation class
class XXXXActivity (override val presenterClassToken: Class < XXXPresenter >)

.
: BaseMVPActivity

above, please refer to


reified T does not need to implement generic parameters because there is no need to get T::class inside it.

according to your idea, just keep the original way of writing Java:

object TUtil {
    fun <T> getT(o: Any, i: Int): T? {
        try {
            return ((o.javaClass
                .genericSuperclass as ParameterizedType).actualTypeArguments[i] as Class<T>)
                .newInstance()
        } catch (e: InstantiationException) {
        } catch (e: IllegalAccessException) {
        } catch (e: ClassCastException) {
        }

        return null
    }
}
Menu