import{_ as n,r as o,o as p,c,b as a,d as s,e as r,a as e}from"./app-mh6GuRj9.js";const i={},t=e(`
这是 KavaRef 相关功能的扩展依赖。
你可以使用如下方式将此模块添加到你的项目中。
在你的项目 SweetDependency
配置文件中添加依赖。
libraries:
com.highcapable.kavaref:
kavaref-extension:
version: +
在你的项目 build.gradle.kts
中配置依赖。
implementation(com.highcapable.kavaref.kavaref.extension)
在你的项目 gradle/libs.versions.toml
中添加依赖。
[versions]
kavaref-extension = "<version>"
[libraries]
kavaref-extension = { module = "com.highcapable.kavaref:kavaref-extension", version.ref = "kavaref-extension" }
在你的项目 build.gradle.kts
中配置依赖。
implementation(libs.kavaref.extension)
请将 <version>
修改为此文档顶部显示的版本。
在你的项目 build.gradle.kts
中配置依赖。
implementation("com.highcapable.kavaref:kavaref-extension:<version>")
请将 <version>
修改为此文档顶部显示的版本。
KavaRef 提供了一些扩展,在处理 Class
对象时会更加方便。
KavaRef 对 Class
的扩展同样添加了 KClass
扩展,作用是调用 KClass.java
,写法上比直接使用 Some::class.java
更加简洁。
例如我们需要使用字符串类名创建一个 Class
对象。
示例如下
val myClass = "com.example.MyClass".toClass()
// 你可以使用带有 OrNull 后缀的方法在找不到 Class 时返回 null 而不是抛出异常
val myClassOrNull = "com.example.MyClass".toClassOrNull()
这些方法统一使用 ClassLoaderProvider
来获取默认的 ClassLoader
,你可以设置默认的 ClassLoader
以影响全局功能。
示例如下
ClassLoaderProvider.classLoader = MyCustomClassLoader()
你也可以手动向 toClass
方法传入一个 ClassLoader
参数来指定使用哪个 ClassLoader
。
在 Kotlin 中引用 Java Class 需要写很长的声明,例如 MyClass::class.java
,此时你可以用以下方式来简化。
示例如下
val myClass = classOf<MyClass>()
你可以使用 isSubclassOf
方法来判断一个 Class
是否是另一个 Class
的子类。
示例如下
val isSubclass = MyClass::class isSubclassOf MySuperClass::class
// 当然,它也有一个对应的反义判断方法
val isNotSubclass = MyClass::class isNotSubclassOf MySuperClass::class
你还可以使用 hasSuperclass
和 hasInterfaces
方法来判断一个 Class
是否有超类或接口。
特别注意
classOf
方法传入的 Class
默认会进行 Java 包装类的拆箱操作,无论你传入的是类似 kotlin.Boolean
还是 java.lang.Boolean
(参考下方的 Java 包装类扩展), 如果你需要避免传入的 Class
被拆箱变为原始类型,你需要明确设置 primitiveType = false
参数。
KavaRef 为 Class
提供了一个方法来方便地创建一个新的实例,你不需要考虑构造参数的类型,你只需要传入对应的参数即可立即创建一个新的实例。
示例如下
val myClass = MyClass::class.createInstance("Hello", 123)
// 你也可以使用带有 OrNull 后缀的方法在创建失败时返回 null 而不是抛出异常
val myClassOrNull = MyClass::class.createInstanceOrNull("Hello", 123)
// createInstance 方法默认仅过滤公开的构造方法,如果你需要调用非公有构造方法,请设置 isPublic = false
val myClassWithPrivateConstructor = MyClass::class.createInstance("Private!", isPublic = false)
// 如果你想指定创建实例的类型使用另一个类型,可以使用以下方法
val mySuperClass = MyClas::class.createInstanceAsType<MySuperClass>("Hello", 123)
// 同样地,你也可以使用带有 OrNull 后缀的方法在创建失败时返回 null 而不是抛出异常
val mySuperClassOrNull = MyClass::class.createInstanceAsTypeOrNull<MySuperClass>("Hello", 123)
小提示
createInstance
方法在成功匹配一次后,会将结果进行缓存防止重复反射造成的性能损耗,它是线程安全的,你可以放心在任何标准场景下使用。
特别注意
当你传入带有 null
的参数时,KavaRef 会尝试将其作为可匹配到条件的一部分 (模糊条件),准确性可能会下降。
createInstance
方法不允许所有参数均为 null
的情况 (条件完全模糊),会直接抛出异常,因为这种情况无法确定要创建哪个实例。
KavaRef 也对 Modifier
进行了扩展,你可以直接使用 Class.isPublic
等方法来判断一个 Class
的修饰符。
KavaRef 提供了 VariousClass
类来装载不确定完整类名的 Class
对象,并返回成功匹配到的第一个。
此功能通常可用于 Android 应用中那些被 R8 混淆后的类名。
示例如下
// 假设在 A 版本中,这个类为 com.example.a,
// 在 B 版本中,这个类为 com.example.b
val myClass = VariousClass("com.example.a", "com.example.b").load()
// 你也可以使用后缀名为 OrNull 的方法在找不到 Class 时返回 null 而不是抛出异常
val myClassOrNull = VariousClass("com.example.a", "com.example.b").loadOrNull()
KavaRef 提供了 LazyClass
类来延迟装载 Class
对象。
你可以在需要时再装载 Class
,而不是在创建时就立即装载,这可以解决一些需要运行时或运行到特定条件下才需要装载的 Class
。
示例如下
// 定义一个不可为空延迟装载的 Class 并托管给 myClass
val myClass by lazyClass("com.example.MyClass")
// 定义一个可为空延迟装载的 Class 并托管给 myClassOrNull
val myClassOrNull by lazyClassOrNull("com.example.MyClass")
// 它亦可支持传入 VariousClass
val otherClassOrNull by lazyClassOrNull(VariousClass("com.example.a", "com.example.b"))
// 在需要时调用即装载
myClass.resolve()
myClassOrNull?.resolve()
otherClassOrNull?.resolve()
KavaRef 还为 ClassLoader
提供了一些实用的扩展方法。
示例如下
// 假设这就是你的 ClassLoader
val classLoader: ClassLoader
// 装载一个 Class,在装载失败时返回 null
val myClassOrNull = classLoader.loadClassOrNull("com.example.MyClass")
// 判断这个 Class 是否存在于当前 ClassLoader 中
val isClassExists = classLoader.hasClass("com.example.MyClass")
在 Java 中,数组的 Class
对象是一个特殊的 Class
对象,通常,我们创建它的方式如下。
例如创建一个 java.lang.String[]
的 Class
对象。
示例如下
val arrayClass = java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
这样写起来非常长,而且不方便维护,所以 KavaRef 提供了一个方法来简化这个过程。
现在,创建 java.lang.String[]
的 Class
对象可以这样写。
示例如下
val arrayClass = ArrayClass(String::class)
KavaRef 提供了一些扩展方法来简化对 Member
的操作。
你可以在任何 Member
对象上使用 makeAccessible
方法来设置其可访问性。
如果 Member
是 AccessibleObject
类型即可生效。
示例如下
// 假设这个是你当前的 Member 对象
val method: Method
// 设置方法可访问
method.makeAccessible()
同样地,KavaRef 也对 Modifier
进行了扩展,你可以直接使用 Member.isPublic
等方法来判断一个 Member
的修饰符。
在 Java 中操作类型或泛型类型时,通常需要使用 Type
接口及其子接口来处理。
KavaRef 提供了一些扩展方法来简化对 Type
的操作。
例如,你可以将一个符合要求的 Type
转换为 Class
对象。
示例如下
val type: Type
val clazz = type.toClass()
// 你也可以使用后缀名为 OrNull 的方法在转换失败时返回 null 而不是抛出异常
val clazzOrNull = type.toClassOrNull()
你也可以将符合要求的 Type
转换为 ParameterizedType
对象。
示例如下
val type: Type
val parameterizedType = type.asParameterizedType()
// 你也可以使用后缀名为 OrNull 的方法在转换失败时返回 null 而不是抛出异常
val parameterizedTypeOrNull = type.asParameterizedTypeOrNull()
你还可以使用以下方式获取超类中的泛型参数数组,这在一些超类与子类的封装操作中会经常用到。
示例如下
val myClass: Class<*>
// 获取 myClass 的超类的泛型参数数组,获取失败或无法获取时将返回空数组
val arguments = myClass.genericSuperclassTypeArguments()
在 Kotlin 中直接使用 Boolean::class
、Byte::class
等方式获取到的是 Java 的原始类型 boolean
、byte
而不是它们的包装类。
如果你需要获取 Java 的包装类,你需要使用完整的 java.lang.Boolean::class
、java.lang.Byte::class
等方式或使用 Boolean::class.javaObjectType
、Byte::class.javaObjectType
。
所以,KavaRef 提供了一些类型别名来处理 Java 的包装类,现在你只需要在这些类型加上 J
前缀即可,例如 JBoolean::class
, 它等价于 java.lang.Boolean::class
,部分类型需要填写全称,例如 JInteger::class
。