其他
Kotlin 泛型擦除不要慌,reified 来帮忙
The following article is from Petterp Author Petterp
Class c1=new ArrayList<Integer>().getClass();
Class c2=new ArrayList<String>().getClass();
// 输出为true
System.out.println(c1==c2);
正是由于类型被擦除,所以就导致一些相关问题,比如不安全的类型转换,模版方法的增多等。
public <T extends Activity> void startActivity(Context context, Class<T> c) {
context.startActivity(new Intent(context, c));
}
inline fun <reified C : Activity> Context.startActivityKtx() {
startActivity(Intent(this, C::class.java))
}
我们利用 扩展函数 + reified 关键字的方式,减少了模版代码,增强了使用体验。 从而让本该在编译阶段被擦除的Activity类型,能够在运行时获取到。
简单理解为:当一个函数被标记为 inline 时,kotlin编译器 会在所有调用这个函数的位置,将方法函数替换为具体的函数体。
例如下面示例与其对应的字节码:
inline fun <reified C : Activity> Context.toAct() {
startActivity(Intent(this, C::class.java))
}
fun test(context: Context) {
context.toAct<MainActivity>()
}
// $FF: synthetic method
public static final void toAct(Context $this$toAct) {
int $i$f$toAct = 0;
Intrinsics.checkNotNullParameter($this$toAct, "$this$toAct");
Intrinsics.reifiedOperationMarker(4, "C");
$this$toAct.startActivity(new Intent($this$toAct, Activity.class));
}
public static final void test(@NotNull Context context) {
Intrinsics.checkNotNullParameter(context, "context");
int $i$f$toAct = false;
context.startActivity(new Intent(context, MainActivity.class));
}
这也就是为什么 reified 必须要增加 inline ,因为其必须内联才能知道具体类型,从而将我们的实际泛型类型更新到具体的调用代码中,从而完成泛型类型 再生 。
Java中无法调用
inline fun <reified C : Activity> Context.toAct() {
...
}
// $FF: synthetic method
public static final void toAct(Context $this$toAct) {
...
}
当然也可以采用 @JvmName(name=" xxx") 等方式避免java调用,但其并不是很优雅。
性能方面
参考
最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!