Java 中的反射机制, 使得我们可以在运行期获取 Java 类的字节码文件中的构造函数, 成员变量, 成员函数等信息. 这一特性使得反射机制被常常用在框架中, 想要比较系统的了解 Kotlin 中的反射, 先从 Java 的反射说起.
Java 中的反射
通常我们写好的. java 源码文件, 经过 javac 的编译, 最终生成了. class 字节码文件. 这些字节码文件是与平台无关的, 使用时通过 Classloader 去加载这些. class 字节码文件, 从而让程序按照我们编写好的业务逻辑运行. Java 的反射主要是从这些. class 文件中获取我们想要得到的内容, 那么 Java 中的反射能够得到哪些内容呢?
获取 Class 对象
Java 是面向对象的语言, 同样的. class 字节码文件也不例外, 想要获取. class 文件中的内容, 就要先获取. class 文件对应的 Class 对象. Java 中获取 Class 对象的方式有三种.
- //1.Class.forName("类名字符串") (注意: 类名字符串必须是全称, 包名 + 类名)
- Class baseInfo = Class.forName("top.sguotao.ReflectionJava");
- //2. 类名. class
- Class object = Object.class;
- //3. 实例对象. getClass()
- Class date = (new Date()).getClass();
- Class testclass = this.getClass();
获取类的构造函数 Constructor
获取 Class 对象之后, 就可以获取其中的构造函数, 从而去创建实例对象. 类的构造函数对应 java.lang.reflect.Constructor. 获取构造函数归纳起来有以下五种方式:
- // 1. 获取参数列表是 parameterTypes, 访问控制符是 public 的构造函数
- public Constructor getConstructor(Class[] parameterTypes)
- // 2. 获取所有访问控制符是 public 的构造函数
- public Constructor[] getConstructors()
- // 3. 获取参数列表是 parameterTypes, 并且是类自身声明的构造函数, 访问控制符包含 public,protected 和 private 的函数.
- public Constructor getDeclaredConstructor(Class[] parameterTypes)
- //4. 获取类自身声明的全部的构造函数, 访问控制符包含 public,protected 和 private 的函数.
- public Constructor[] getDeclaredConstructors()
- //5. 如果类声明在其它类的构造函数中, 返回该类所在的构造函数, 如果存在则返回, 不存在返回 null
- public Constructor getEnclosingConstructor()
获取类的成员变量
类的成员变量对应的是 java.lang.reflect.Field, 获取成员变量归纳起来有以下四种方式:
- //1. 获取 "名称是 name" 的 public 的成员变量(包括从基类继承的, 从接口实现的所有 public 成员变量)
- public Field getField(String name)
- //2. 获取全部的 public 成员变量(包括从基类继承的, 从接口实现的所有 public 成员变量)
- public Field[] getFields()
- //3. 获取 "名称是 name", 并且是类自身声明的成员变量, 包含 public,protected 和 private 成员变量.
- public Field getDeclaredField(String name)
- //4. 获取全部的类自身声明的成员变量, 包含 public,protected 和 private 成员变量.
- public Field[] getDeclaredFields()
获取类的成员函数
类的成员函数对应的是 java.lang.reflect.Method, 获取成员函数归纳起来有下面 5 种方式:
- // 1. 获取函数名是 name, 参数是 parameterTypes 的 public 的函数(包括从基类继承的, 从接口实现的所有 public 函数)
- public Method getMethod(String name, Class[] parameterTypes)
- //2. 获取全部的 public 的函数(包括从基类继承的, 从接口实现的所有 public 函数)
- public Method[] getMethods()
- //3. 获取函数名 name, 参数是 parameterTypes, 并且是类自身声明的函数, 包含 public,protected 和 private 方法.
- public Method getDeclaredMethod(String name, Class[] parameterTypes)
- //4. 获取全部的类自身声明的函数, 包含 public,protected 和 private 方法.
- public Method[] getDeclaredMethods()
- //5. 如果这个类是其它类中某个方法的内部类, 调用 getEnclosingMethod()就是这个类所在的方法; 若不存在, 返回 null.
- public Method getEnclosingMethod()
获取类的其它信息
获取类的注解信息, 对应的是 java.lang.annotation.Annotation 接口, 获取类的注解信息归纳起来有下面 3 种方法:
- //1. 获取类的 annotationClass 类型的注解 (包括从基类继承的, 从接口实现的所有 public 成员变量)
- public Annotation<A> getAnnotation(Class annotationClass)
- //2. 获取类的全部注解 (包括从基类继承的, 从接口实现的所有 public 成员变量)
- public Annotation[] getAnnotations()
- //3. 获取类自身声明的全部注解 (包含 public,protected 和 private 成员变量)
- public Annotation[] getDeclaredAnnotations()
获取类的接口和基类的信息, 对应的是 java.lang.reflect.Type 接口, 获取类的接口和基类信息有下面两个方法:
- // 获取实现的全部接口
- public Type[] getGenericInterfaces()
- // 获取基类
- public Type getGenericSuperclass()
获取类的其它描述信息.
- //1. 获取类名
- public String getSimpleName()
- //2. 获取完整类名
- public String getName()
- //3. 判断类是不是枚举类
- public boolean isEnum()
- //4. 判断 obj 是不是类的实例对象
- public boolean isInstance(Object obj)
- //5. 判断类是不是接口
- public boolean isInterface()
- //6. 判断类是不是本地类, 所谓本地类, 就是定义在方法内部的类.
- public boolean isLocalClass()
- //7. 判断类是不是成员类, 所谓成员类, 就是常见的内部类, 是指不在代码块, 构造函数和成员方法中的内部类.
- public boolean isMemberClass()
- //8. 判断类是不是基本类型. 基本类型, 包括 void 和 boolean,byte,char,short,int,long,float 和 double 这几种类型.
- public boolean isPrimitive()
- //1. 通过实例. javaClass
- var hello = HelloWorld()
- hello.javaClass
- //2. 通过类 Kclass 类的. java 属性
- HelloWorld::class.java
- //1. 通过类::class 的方式获取 Kclass 实例
- val clazz1: KClass<*> = HelloWorld::class
- //2. 通过实例. javaClass.kotlin 获取 Kclass 实例
- var hello = HelloWorld()
- val clazz2 = hello.javaClass.kotlin
- // 返回这个类的所有构造器
- public val constructors: Collection<KFunction<T>>
- // 返回类可访问的所有函数和属性, 包括继承自基类的, 但是不包括构造器
- override val members: Collection<KCallable<*>>
- // 返回类声明的所有函数
- val KClass<*>.declaredFunctions: Collection<KFunction<*>>
- // 返回类的扩展函数
- val KClass<*>.declaredMemberExtensionFunctions: Collection<KFunction<*>>
- // 返回类的扩展属性
- val <T : Any> KClass<T>.declaredMemberExtensionProperties: Collection<KProperty2<T, *, *>>
- // 返回类自身声明的成员函数
- val KClass<*>.declaredMemberFunctions: Collection<KFunction<*>>
- // 返回类自身声明的成员变量(属性)
- val <T : Any> KClass<T>.declaredMemberProperties: Collection<KProperty1<T, *>>
- //1. 返回类的名字
- public val simpleName: String?
- //2. 返回类的全包名
- public val qualifiedName: String?
- //3. 如果这个类声明为 object, 则返回其实例, 否则返回 null
- public val objectInstance: T?
- //4. 返回类的可见性
- @SinceKotlin("1.1")
- public val visibility: KVisibility?
- //5. 判断类是否为 final 类(在 Kotlin 中, 类默认是 final 的, 除非这个类声明为 open 或者 abstract)
- @SinceKotlin("1.1")
- public val isFinal: Boolean
- //6. 判断类是否是 open 的(abstract 类也是 open 的), 表示这个类可以被继承
- @SinceKotlin("1.1")
- public val isOpen: Boolean
- //7. 判断类是否为抽象类
- @SinceKotlin("1.1")
- public val isAbstract: Boolean
- //8. 判断类是否为密封类, 密封类: 用 sealed 修饰, 其子类只能在其内部定义
- @SinceKotlin("1.1")
- public val isSealed: Boolean
- //9. 判断类是否为 data 类
- @SinceKotlin("1.1")
- public val isData: Boolean
- //10. 判断类是否为成员类
- @SinceKotlin("1.1")
- public val isInner: Boolean
- //11. 判断类是否为 companion object
- @SinceKotlin("1.1")
- public val isCompanion: Boolean
- //12. 返回类中定义的其他类, 包括内部类 (inner class 声明的) 和嵌套类(class 声明的)
- public val nestedClasses: Collection<KClass<*>>
- //13. 判断一个对象是否为此类的实例
- @SinceKotlin("1.1")
- public fun isInstance(value: Any?): Boolean
- //14. 返回这个类的泛型列表
- @SinceKotlin("1.1")
- public val typeParameters: List<KTypeParameter>
- //15. 类其直接基类的列表
- @SinceKotlin("1.1")
- public val supertypes: List<KType>
- //16. 返回类所有的基类
- val KClass<*>.allSuperclasses: Collection<KClass<*>>
- //17. 返回类的伴生对象 companionObject
- val KClass<*>.companionObject: KClass<*>?
- Kotlin Bootcamp for Programmers https://classroom.udacity.com/courses/ud9011
- Kotlin Koans
来源: https://juejin.im/post/5be5576ef265da61616e331d