Kotlin 中内联函数中的代码会在编译的时候自动被替换到调用它的地方,这样也就不存在泛型擦除的问题,因为代码在编译之后会直接使用实际的类型来替代内联函数中的泛型声明,所以,Kotlin 中是可以将内联函数中的泛型进行实化的。
泛型实化有两个条件:
-
函数必须是内联函数,就是用 inline 关键字来修饰的函数
-
在声明泛型的地方必须加上 reified 关键字来表示该泛型要进行实化
inline fun <reified T> getGenericType() = T::class.java
这个函数实现了 Java 中完全不可能实现的功能是获取泛型实际类型。T.class 这样的语法在 Java 中是不合法的,而在 Kotlin 中,借助泛型实化功能就可以使用 T::class.java 这样的语法了。
测试如下
fun main() {
val result1 = getGenericType()val result2 = getGenericType<Int>()
println(result1)
println(result2)
}
Android 中的应用
我们启动一个一个 Activity 可以这么写
val intent = Intent(context,TestActivity::class.java)
context.startActivity(intent)
使用 Kotlin 泛型实化功能,可以这样写
inline fun <reified T> startActivity(context : Context) {
val intent = Intent(context,T::class.java)
context.startActivity(intent)
}
现在,如想要启动 TestActivity,只需要这样写就可以了
startActivity(context)
不过,现在的 startActivity() 函数还是有问题的,因为通常在启动 Activity 的时候会使用 Intent 附带一些参数,我们可以借助高阶函数来解决这个问题:
inline fun <reified T> startActivity(context : Context,block : Intent.() -> Unit) {
val intent = Intent(context,T::class.java)
intent.block()
context.startActivity(intent)
}
这个 startActivity() 函数增加一个函数参数类型,并且它的函数类型是定义带 Intent 类当作的。在创建完 Intent 的实例之后,随即调用该函数类型参数,并把 Intent 的实例传入,这样调用 startActivity() 函数的时候就可以在 Lambda 表达式中为 Intent 传递参数了,如下所示
startActivity(context){
putExtra("param1","data1")
putExtra("param2","data2)
}
泛型实化Kotlin 中内联函数中的代码会在编译的时候自动被替换到调用它的地方,这样也就不存在泛型擦除的问题,因为代码在编译之后会直接使用实际的类型来替代内联函数中的泛型声明,所以,Kotlin 中是可以将内联函数中的泛型进行实化的。泛型实化有两个条件:函数必须是内联函数,就是用 inline 关键字来修饰的函数在声明泛型的地方必须加上 reified 关键字来表示该泛型要进行实化示例如...
0. 引子
Kotlin
100% 与 Java 兼容,所以抛开语言表面上面的种种特质之外,背后的语言逻辑或者说“灵魂”与 Java 总是想通的。本文只涉及
Kotlin
Jvm,
Kotlin
Js、
Kotlin
Native 的具体实现可能有差异。
最近一段时间在网上发了一套
Kotlin
的入门视频,涵盖了基础语法、面向对象、高阶函数、DSL、协程等比较有特色的知识点,不过有朋友提出了疑问:这门课为什么不专门讲讲
泛型
、反射和注解呢?
我最早听到这个问题的时候,反应比较懵逼,因为我居然没有感觉到 K
Kotlin
中声明和使用
泛型
类及
泛型
函数的基本概念和Java类似。
同时
Kotlin
引入了新的概念,比如室化类型参数和声明点变型。这些概念对于我们来说可能很新奇。
实化
类型参数: 允许你在运行时的内联函数调用引用作为类型实参的具体类型(对普通的类和函数来说,这样行不通,因为类型实参在运行时会被擦除)。
声明点变型: 可以说明一个带类型参数的
泛型
类型,是否是另一个
泛型
类型的字类型或者超类型,它们的基础类型相同但类型参数不同。
例如,它能调节是否可以把List<Int> 类型的参数传给期望List&
//
Kotlin
中
泛型
变换实现
class
KtBase9<T>(val isMap: Boolean = false, val inputType: T) {
//模仿RxJava T是要变化的输入类型 R是变化后的输出类型
//调用map返回的类型是 R? == 有可能是R或者null
inline fun <R> map(mapAction: (T) -> R): R? = mapAction(inputType).takeIf { isM.
在Java中使用
Class
很常见的就是,xxx类.
class
,比如我们在startActivity的时候startActivity(new Intent(this, OtherActivity.
class
)); 这里接收的就是
CLass
1、
Class
c = person.get
Class
(); //对象获...
泛型
类型参数
泛型
允许你定义带类型形参的类型。当这种类型的实例被创建出来的时候,类型形参被替换成称为类型实参的具体类型。
使用方式和 Java 一样:List<String>,Map<K, V>。
同样,
Kotlin
也可以自动推导类型:
val authors = listOf("Dmitry", "Svetlana")
和 Java 不同的是,
Kotlin
始终要求类型实参要么被显示的说明,要么能被编译期推导出来。
在 Java 中,可以使用如下方法来
获取
List 的
泛型
类型:
1. 使用 List 的 get
Class
() 方法
获取
List 对象的
Class
对象,然后使用
Class
对象的 getGenericSuper
class
() 方法
获取
List 对象的直接超类的 Type。
2. 使用 List 的 get
Class
() 方法
获取
List 对象的
Class
对象,然后使用
Class
对象的 getTypeParameters() 方法
获取
List 对象的类型参数。
下面是示例代码:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public
class
Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
//
获取
List 对象的
Class
对象
Class
<?> clazz = list.get
Class
();
//
获取
List 对象的直接超类的 Type
Type type = clazz.getGenericSuper
class
();
// 如果 type 是 ParameterizedType 类型,则说明它是一个带
泛型
的类型
if (type instanceof ParameterizedType) {
//
获取
List 对象的
泛型
类型
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
System.out.println(actualTypeArguments[0]); // 输出:
class
java.lang.String
//
获取
List 对象的类型参数
TypeVariable<?>[] typeParameters = clazz.getTypeParameters();
System.out.println(typeParameters[0].getName()); // 输出: E
注意,如果 List 对象是通过赋值的方式得到的,而非通过 new 运算符创建的,则无法使用以上方法
获取
泛型
类型。例如:
List<String> list = new ArrayList<>();
List anotherList = list;
// 无法使用以上方法获