pexels-2876033.jpg
Kotlin 跟 Java 可以无缝衔接,因此 Kotlin 能够使用 Java 的反射机制。另外,Kotlin 也有自己的反射机制,需要额外地引入 kotlin-reflect.jar。
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
kotlin-reflect.jar 中包含 kotlin.reflect.full 和 kotlin.reflect.jvm。
- kotlin.reflect.full 是主要的 Kotlin 反射 API
- kotlin.reflect.jvm 用于 Kotlin 反射和 Java 反射的互操作。
Kotlin 反射的特性包含:
- 提供对属性和可空类型的访问权限,这是由于 Java 没有属性和可空类型的概念。
- Kotlin 反射不是 Java 反射的替代品,而是功能的增强。
- 可以使用 Kotlin 反射来访各种基于 JVM 语言编写的代码。
下面以 Java 的反射和 Kotlin 的反射进行对比。
一. 类引用,获取 Class 对象
Java 获取 Class 对象的方式
- Class.forName("完整的包名+类名")
Class<?> clazz = Class.forName("xxx.xxx.MyClass")
- 类名.class
Class<?> clazz = MyClass.class;
- 实例对象.getClass()
MyClass obj = new MyClass();
Class<?> clazz = obj.getClass();
Kotlin 获取 Class 对象的方式
- 调用的类是 Java 类,需要添加 .java 后缀( KClass 的扩展属性 java)
val clazz = MyClass::class.java
- 添加 Java 实例对象的.javaClass后缀(Java 实例对象的扩展属性 javaClass)。
val obj = MyClass()
val clazz = obj.javaClass
- 调用的类是 Kotlin 类
val clazz = MyClass::class
此时 clazz 的类型是 KClass 类型,KClass 的一个实例表示对 Kotlin 类的引用。KClass 也是 Kotlin 反射 API 的主要入口。
在 Kotlin 中,字节码对应的类也是 kotlin.reflect.KClass。
Kotlin 的引用类有两种方式:类名::class
和对象::class
,它们获取的都是相同的 KClass 实例。
即处于同一个类加载器中,给定的类型只能返回一个 KClass 实例。即使多次尝试实例化 KClass, 仍然只能获取同一对象的引用, Kotlin 不会创建新的引用。
二. 构造函数引用,获取类的构造函数
Java 获取类的构造函数
Java 在获取 Class 实例之后,可以获取其中的构造函数。Java 获取类的构造函数对应的是 java.lang.reflect.Constructor,有以下五种方式:
// 获取参数列表是 parameterTypes,访问 public 的构造函数
public Constructor getConstructor(Class[] parameterTypes)
// 获取所有 public 构造函数
public Constructor[] getConstructors()
// 获取参数列表是 parameterTypes,并且是类自身声明的构造函数,访问控制符包含 public、protected 和 private 的函数。
public Constructor getDeclaredConstructor(Class[] parameterTypes)
// 获取类自身声明的全部的构造函数,包含 public、protected和private 的函数。
public Constructor[] getDeclaredConstructors()
// 如果类声明在其它类的构造函数中,返回该类所在的构造函数,如果存在则返回,不存在返回null
public Constructor getEnclosingC