commit e9fb0169d8f8b5f24861fbddf11ec1d6dc625421 Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed Jun 25 11:38:33 2025 +0000 Deploy to GitHub pages diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..bde5785 --- /dev/null +++ b/404.html @@ -0,0 +1,34 @@ + + +
+ + + + + +Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
abstract class BaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
这是
Class
与Member
查找类功能的基本类实现。
inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
+
Change Records
v1.0.0
first
Function Illustrate
字节码下标筛选实现类。
fun index(num: Int)
+
Change Records
v1.0.0
first
Function Illustrate
设置下标。
若 index
小于零则为倒序,此时可以使用 IndexTypeConditionSort.reverse
方法实现。
可使用 IndexTypeConditionSort.first
和 IndexTypeConditionSort.last
设置首位和末位筛选条件。
fun index(): IndexTypeConditionSort
+
Change Records
v1.0.0
first
Function Illustrate
得到下标。
inner class IndexTypeConditionSort internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
字节码下标排序实现类。
fun first()
+
Change Records
v1.0.0
first
Function Illustrate
设置满足条件的第一个。
fun last()
+
Change Records
v1.0.0
first
Function Illustrate
设置满足条件的最后一个。
fun reverse(num: Int)
+
Change Records
v1.0.0
first
Function Illustrate
`,51),l=[t];function p(c,r){return e(),n("div",null,l)}const i=s(o,[["render",p],["__file","BaseFinder.html.vue"]]);export{i as default}; diff --git a/assets/BaseFinder.html-bAM0SzKR.js b/assets/BaseFinder.html-bAM0SzKR.js new file mode 100644 index 0000000..87f3e7c --- /dev/null +++ b/assets/BaseFinder.html-bAM0SzKR.js @@ -0,0 +1,9 @@ +import{_ as s,o as e,c as a,a as n}from"./app-Un_zyw_U.js";const o={},p=n(`设置倒序下标。
abstract class BaseFinder
+
变更记录
v1.0.0
添加
功能描述
这是
Class
与Member
查找类功能的基本类实现。
inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
+
变更记录
v1.0.0
添加
功能描述
字节码下标筛选实现类。
fun index(num: Int)
+
变更记录
v1.0.0
添加
功能描述
设置下标。
若 index
小于零则为倒序,此时可以使用 IndexTypeConditionSort.reverse
方法实现。
可使用 IndexTypeConditionSort.first
和 IndexTypeConditionSort.last
设置首位和末位筛选条件。
fun index(): IndexTypeConditionSort
+
变更记录
v1.0.0
添加
功能描述
得到下标。
inner class IndexTypeConditionSort internal constructor()
+
变更记录
v1.0.0
添加
功能描述
字节码下标排序实现类。
fun first()
+
变更记录
v1.0.0
添加
功能描述
设置满足条件的第一个。
fun last()
+
变更记录
v1.0.0
添加
功能描述
设置满足条件的最后一个。
fun reverse(num: Int)
+
变更记录
v1.0.0
添加
功能描述
`,50),l=[p];function t(c,d){return e(),a("div",null,l)}const i=s(o,[["render",t],["__file","BaseFinder.html.vue"]]);export{i as default}; diff --git a/assets/ComponentTypeFactory.html-986b1Uh7.js b/assets/ComponentTypeFactory.html-986b1Uh7.js new file mode 100644 index 0000000..5822907 --- /dev/null +++ b/assets/ComponentTypeFactory.html-986b1Uh7.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-6c58c435","path":"/zh-cn/api/public/com/highcapable/yukireflection/type/android/ComponentTypeFactory.html","title":"ComponentTypeFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[],"git":{"updatedTime":1696445455000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/type/android/ComponentTypeFactory.md"}');export{e as data}; diff --git a/assets/ComponentTypeFactory.html-FeM6EBQs.js b/assets/ComponentTypeFactory.html-FeM6EBQs.js new file mode 100644 index 0000000..f37ab03 --- /dev/null +++ b/assets/ComponentTypeFactory.html-FeM6EBQs.js @@ -0,0 +1 @@ +import{_ as n,r as a,o as r,c,b as o,d as e,e as s,a as i}from"./app-Un_zyw_U.js";const p={},l=i('设置倒序下标。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
',6),d={href:"https://github.com/HighCapable/YukiReflection/blob/master/yukireflection/src/main/java/com/highcapable/yukireflection/type/android/ComponentTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"};function h(m,u){const t=a("ExternalLinkIcon");return r(),c("div",null,[l,o("p",null,[e("详情可 "),o("a",d,[e("点击这里"),s(t)]),e(" 进行查看。")])])}const _=n(p,[["render",h],["__file","ComponentTypeFactory.html.vue"]]);export{_ as default}; diff --git a/assets/ComponentTypeFactory.html-MSABhHlb.js b/assets/ComponentTypeFactory.html-MSABhHlb.js new file mode 100644 index 0000000..ad3a01a --- /dev/null +++ b/assets/ComponentTypeFactory.html-MSABhHlb.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-7f47f9f8","path":"/en/api/public/com/highcapable/yukireflection/type/android/ComponentTypeFactory.html","title":"ComponentTypeFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[],"git":{"updatedTime":1696445455000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/type/android/ComponentTypeFactory.md"}');export{e as data}; diff --git a/assets/ComponentTypeFactory.html-Wy4oe3qj.js b/assets/ComponentTypeFactory.html-Wy4oe3qj.js new file mode 100644 index 0000000..6852681 --- /dev/null +++ b/assets/ComponentTypeFactory.html-Wy4oe3qj.js @@ -0,0 +1 @@ +import{_ as n,r as a,o as c,c as r,b as o,d as e,e as s,a as p}from"./app-Un_zyw_U.js";const d={},l=p('这是一个预置反射类型的常量类,主要为
Android
相关组件的Class
内容,跟随版本更新会逐一进行增加。
变更记录
v1.0.0
添加
功能描述
',5),i={href:"https://github.com/HighCapable/YukiReflection/blob/master/yukireflection/src/main/java/com/highcapable/yukireflection/type/android/ComponentTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"};function m(_,h){const t=a("ExternalLinkIcon");return c(),r("div",null,[l,o("p",null,[e("详情可 "),o("a",i,[e("点击这里"),s(t)]),e(" 进行查看。")])])}const f=n(d,[["render",m],["__file","ComponentTypeFactory.html.vue"]]);export{f as default}; diff --git a/assets/ConstructorFinder.html-HZlOD583.js b/assets/ConstructorFinder.html-HZlOD583.js new file mode 100644 index 0000000..b7e5790 --- /dev/null +++ b/assets/ConstructorFinder.html-HZlOD583.js @@ -0,0 +1,66 @@ +import{_ as s,o as n,c as o,a}from"./app-Un_zyw_U.js";const e={},l=a(`这是一个预置反射类型的常量类,主要为
Android
相关组件的Class
内容,跟随版本更新会逐一进行增加。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ConstructorFinder internal constructor(override val classSet: Class<*>) : MemberBaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
查找类。
可通过指定类型查找指定 Constructor
或一组 Constructor
。
var paramCount: Int
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
标识符筛选条件。
可不设置筛选条件,默认模糊查找并取第一个匹配的 Constructor
。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun emptyParam(): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
空参数、无参数。
fun param(vararg paramType: Any): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。
Pay Attention
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun param(conditions: ObjectsConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数条件。
Pay Attention
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(num: Int): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数。
若参数个数小于零则忽略并使用 param
。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(numRange: IntRange): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
Change Records
v1.0.0
first
Function Illustrate
设置在
classSet
的所有父类中查找当前Constructor
。
Notice
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
重查找实现类,可累计失败次数直到查找成功。
inline fun constructor(initiate: ConstructorConditions)
+
Change Records
v1.0.0
first
Function Illustrate
创建需要重新查找的
Constructor
。
你可以添加多个备选 Constructor
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Constructor<*>>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
modified
initiate
类型由 HashSet
修改为 MutableList
Function Illustrate
当在
RemedyPlan
中找到结果时。
Function Example
你可以方便地对重查找的 Constructor
实现 onFind
方法。
The following example
constructor {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建监听结果事件方法体。
Function Example
你可以使用 lambda 形式创建 Result
类。
The following example
constructor {
+ // Your code here.
+}.result {
+ get().call()
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
fun get(): Instance
+
Change Records
v1.0.0
first
Function Illustrate
获得
Constructor
实例处理类。
若有多个 Constructor
结果只会返回第一个。
Pay Attention
若你设置了 remedys 请使用 wait 回调结果方法。
Function Example
你可以通过获得方法所在实例来执行构造方法创建新的实例对象。
The following example
constructor {
+ // Your code here.
+}.get().call()
+
你可以 cast
构造方法为指定类型的实例对象。
The following example
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>()
+
Pay Attention
若构造方法含有参数则后方参数必填。
The following example
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>("param1", "param2")
+
fun all(): MutableList<Instance>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Constructor
实例处理类数组。
返回全部查找条件匹配的多个 Constructor
实例结果。
Function Example
你可以通过此方法来获得当前条件结果中匹配的全部 Constructor
。
The following example
constructor {
+ // Your code here.
+}.all().forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Constructor<*>?
+
Change Records
v1.0.0
first
Function Illustrate
得到
Constructor
本身。
若有多个 Constructor
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Constructor<*>>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Constructor
本身数组。
返回全部查找条件匹配的多个 Constructor
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(initiate: Instance.() -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
获得
Constructor
实例处理类,配合RemedyPlan
使用。
若有多个 Constructor
结果只会返回第一个。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(initiate: MutableList<Instance>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
modified
initiate
类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Constructor
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Constructor
实例结果。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建
Constructor
重查找功能。
Function Example
当你遇到一种 Constructor
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchConstructor
捕获异常二次查找 Constructor
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
The following example
constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
监听找不到
Constructor
时。
只会返回第一次的错误信息,不会返回 RemedyPlan
的错误信息。
fun ignored(): Result
+
Change Records
v1.0.0
first
Function Illustrate
忽略异常并停止打印任何错误日志。
Notice
此时若要监听异常结果,你需要手动实现 onNoSuchConstructor 方法。
inner class Instance internal constructor(private val constructor: Constructor<*>?)
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
实例处理类。
fun call(vararg args: Any?): Any?
+
Change Records
v1.0.0
first
Function Illustrate
执行
Constructor
创建目标实例,不指定目标实例类型。
fun <T> newInstance(vararg args: Any?): T?
+
Change Records
v1.0.0
first
Function Illustrate
`,235),t=[l];function p(c,r){return n(),o("div",null,t)}const i=s(e,[["render",p],["__file","ConstructorFinder.html.vue"]]);export{i as default}; diff --git a/assets/ConstructorFinder.html-SqtdCIul.js b/assets/ConstructorFinder.html-SqtdCIul.js new file mode 100644 index 0000000..85e7179 --- /dev/null +++ b/assets/ConstructorFinder.html-SqtdCIul.js @@ -0,0 +1,66 @@ +import{_ as s,o as n,c as o,a}from"./app-Un_zyw_U.js";const e={},l=a(`执行
Constructor
创建目标实例 ,指定T
目标实例类型。
class ConstructorFinder internal constructor(override val classSet: Class<*>) : MemberBaseFinder
+
变更记录
v1.0.0
添加
功能描述
Constructor
查找类。
可通过指定类型查找指定 Constructor
或一组 Constructor
。
var paramCount: Int
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
标识符筛选条件。
可不设置筛选条件,默认模糊查找并取第一个匹配的 Constructor
。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun emptyParam(): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
空参数、无参数。
fun param(vararg paramType: Any): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。
特别注意
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun param(conditions: ObjectsConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数条件。
特别注意
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(num: Int): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数。
若参数个数小于零则忽略并使用 param
。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(numRange: IntRange): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
变更记录
v1.0.0
添加
功能描述
设置在
classSet
的所有父类中查找当前Constructor
。
注意
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
变更记录
v1.0.0
添加
功能描述
Constructor
重查找实现类,可累计失败次数直到查找成功。
inline fun constructor(initiate: ConstructorConditions)
+
变更记录
v1.0.0
添加
功能描述
创建需要重新查找的
Constructor
。
你可以添加多个备选 Constructor
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
变更记录
v1.0.0
添加
功能描述
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Constructor<*>>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 HashSet
修改为 MutableList
功能描述
当在
RemedyPlan
中找到结果时。
功能示例
你可以方便地对重查找的 Constructor
实现 onFind
方法。
示例如下
constructor {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
变更记录
v1.0.0
添加
功能描述
Constructor
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建监听结果事件方法体。
功能示例
你可以使用 lambda 形式创建 Result
类。
示例如下
constructor {
+ // Your code here.
+}.result {
+ get().call()
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
fun get(): Instance
+
变更记录
v1.0.0
添加
功能描述
获得
Constructor
实例处理类。
若有多个 Constructor
结果只会返回第一个。
特别注意
若你设置了 remedys 请使用 wait 回调结果方法。
功能示例
你可以通过获得方法所在实例来执行构造方法创建新的实例对象。
示例如下
constructor {
+ // Your code here.
+}.get().call()
+
你可以 cast
构造方法为指定类型的实例对象。
示例如下
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>()
+
特别注意
若构造方法含有参数则后方参数必填。
示例如下
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>("param1", "param2")
+
fun all(): MutableList<Instance>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 ArrayList
修改为 MutableList
功能描述
获得
Constructor
实例处理类数组。
返回全部查找条件匹配的多个 Constructor
实例结果。
功能示例
你可以通过此方法来获得当前条件结果中匹配的全部 Constructor
。
示例如下
constructor {
+ // Your code here.
+}.all().forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Constructor<*>?
+
变更记录
v1.0.0
添加
功能描述
得到
Constructor
本身。
若有多个 Constructor
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Constructor<*>>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
功能描述
得到
Constructor
本身数组。
返回全部查找条件匹配的多个 Constructor
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(initiate: Instance.() -> Unit)
+
变更记录
v1.0.0
添加
功能描述
获得
Constructor
实例处理类,配合RemedyPlan
使用。
若有多个 Constructor
结果只会返回第一个。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(initiate: MutableList<Instance>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 ArrayList
修改为 MutableList
功能描述
获得
Constructor
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Constructor
实例结果。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建
Constructor
重查找功能。
功能示例
当你遇到一种 Constructor
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchConstructor
捕获异常二次查找 Constructor
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
示例如下
constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
监听找不到
Constructor
时。
只会返回第一次的错误信息,不会返回 RemedyPlan
的错误信息。
fun ignored(): Result
+
变更记录
v1.0.0
添加
功能描述
忽略异常并停止打印任何错误日志。
注意
此时若要监听异常结果,你需要手动实现 onNoSuchConstructor 方法。
inner class Instance internal constructor(private val constructor: Constructor<*>?)
+
变更记录
v1.0.0
添加
功能描述
Constructor
实例处理类。
fun call(vararg args: Any?): Any?
+
变更记录
v1.0.0
添加
功能描述
执行
Constructor
创建目标实例,不指定目标实例类型。
fun <T> newInstance(vararg args: Any?): T?
+
变更记录
v1.0.0
添加
功能描述
`,234),p=[l];function t(c,r){return n(),o("div",null,p)}const i=s(e,[["render",t],["__file","ConstructorFinder.html.vue"]]);export{i as default}; diff --git a/assets/ConstructorFinder.html-WBhuluIb.js b/assets/ConstructorFinder.html-WBhuluIb.js new file mode 100644 index 0000000..be71e75 --- /dev/null +++ b/assets/ConstructorFinder.html-WBhuluIb.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-b3220076","path":"/en/api/public/com/highcapable/yukireflection/finder/members/ConstructorFinder.html","title":"ConstructorFinder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"param - method","slug":"param-method-1","link":"#param-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-2","link":"#paramcount-method-2","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchConstructor - method","slug":"onnosuchconstructor-method","link":"#onnosuchconstructor-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]}]}],"git":{"updatedTime":1696172435000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/members/ConstructorFinder.md"}');export{e as data}; diff --git a/assets/ConstructorFinder.html-_FNxdKVs.js b/assets/ConstructorFinder.html-_FNxdKVs.js new file mode 100644 index 0000000..3e0761e --- /dev/null +++ b/assets/ConstructorFinder.html-_FNxdKVs.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-722cd474","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/members/ConstructorFinder.html","title":"ConstructorFinder - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"param - method","slug":"param-method-1","link":"#param-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-2","link":"#paramcount-method-2","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchConstructor - method","slug":"onnosuchconstructor-method","link":"#onnosuchconstructor-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]}]}],"git":{"updatedTime":1696172435000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/members/ConstructorFinder.md"}');export{e as data}; diff --git a/assets/ConstructorRules.html-DYOYWZvf.js b/assets/ConstructorRules.html-DYOYWZvf.js new file mode 100644 index 0000000..df13787 --- /dev/null +++ b/assets/ConstructorRules.html-DYOYWZvf.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-ec153654","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/ConstructorRules.html","title":"ConstructorRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"param - method","slug":"param-method-1","link":"#param-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]}],"git":{"updatedTime":1695808915000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/ConstructorRules.md"}');export{e as data}; diff --git a/assets/ConstructorRules.html-HoOS6Lpr.js b/assets/ConstructorRules.html-HoOS6Lpr.js new file mode 100644 index 0000000..73a4c03 --- /dev/null +++ b/assets/ConstructorRules.html-HoOS6Lpr.js @@ -0,0 +1,9 @@ +import{_ as s,o,c as a,a as n}from"./app-Un_zyw_U.js";const e={},t=n(`执行
Constructor
创建目标实例 ,指定T
目标实例类型。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ConstructorRules internal constructor(private val rulesData: ConstructorRulesData) : BaseRules
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
查找条件实现类。
var paramCount: Int
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
标识符筛选条件。
可不设置筛选条件。
fun emptyParam()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
空参数、无参数。
fun param(vararg paramType: Any)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。
Pay Attention
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
fun param(conditions: ObjectsConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数条件。
Pay Attention
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
fun paramCount(numRange: IntRange)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
fun paramCount(conditions: CountConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
class ConstructorRules internal constructor(private val rulesData: ConstructorRulesData) : BaseRules
+
变更记录
v1.0.0
添加
功能描述
Constructor
查找条件实现类。
var paramCount: Int
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
标识符筛选条件。
可不设置筛选条件。
fun emptyParam()
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
空参数、无参数。
fun param(vararg paramType: Any)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。
特别注意
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
fun param(conditions: ObjectsConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数条件。
特别注意
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
fun paramCount(numRange: IntRange)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
fun paramCount(conditions: CountConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class CountRules private constructor()
+
Change Records
v1.0.0
first
Function Illustrate
这是一个模糊
Class
、Member
数组 (下标) 个数条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
fun Int.isZero(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否为 0。
fun Int.moreThan(count: Int): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
大于
count
。
fun Int.lessThan(count: Int): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
小于
count
。
fun Int.inInterval(countRange: IntRange): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
`,32),l=[t];function c(p,r){return e(),n("div",null,l)}const i=s(a,[["render",c],["__file","CountRules.html.vue"]]);export{i as default}; diff --git a/assets/CountRules.html-qumSB8gY.js b/assets/CountRules.html-qumSB8gY.js new file mode 100644 index 0000000..204a2d7 --- /dev/null +++ b/assets/CountRules.html-qumSB8gY.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-6f96d791","path":"/en/api/public/com/highcapable/yukireflection/finder/base/rules/CountRules.html","title":"CountRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"Int.isZero - i-ext-method","slug":"int-iszero-i-ext-method","link":"#int-iszero-i-ext-method","children":[]},{"level":2,"title":"Int.moreThan - i-ext-method","slug":"int-morethan-i-ext-method","link":"#int-morethan-i-ext-method","children":[]},{"level":2,"title":"Int.lessThan - i-ext-method","slug":"int-lessthan-i-ext-method","link":"#int-lessthan-i-ext-method","children":[]},{"level":2,"title":"Int.inInterval - i-ext-method","slug":"int-ininterval-i-ext-method","link":"#int-ininterval-i-ext-method","children":[]}],"git":{"updatedTime":1674726569000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/base/rules/CountRules.md"}');export{e as data}; diff --git a/assets/CountRules.html-z8W_vwvZ.js b/assets/CountRules.html-z8W_vwvZ.js new file mode 100644 index 0000000..909bae2 --- /dev/null +++ b/assets/CountRules.html-z8W_vwvZ.js @@ -0,0 +1,6 @@ +import{_ as s,o as n,c as o,a as e}from"./app-Un_zyw_U.js";const a={},t=e(`在
countRange
区间 A ≤ this ≤ B。
class CountRules private constructor()
+
变更记录
v1.0.0
添加
功能描述
这是一个模糊
Class
、Member
数组 (下标) 个数条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
fun Int.isZero(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否为 0。
fun Int.moreThan(count: Int): Boolean
+
变更记录
v1.0.0
添加
功能描述
大于
count
。
fun Int.lessThan(count: Int): Boolean
+
变更记录
v1.0.0
添加
功能描述
小于
count
。
fun Int.inInterval(countRange: IntRange): Boolean
+
变更记录
v1.0.0
添加
功能描述
`,31),l=[t];function c(p,r){return n(),o("div",null,l)}const i=s(a,[["render",c],["__file","CountRules.html.vue"]]);export{i as default}; diff --git a/assets/CurrentClass.html-ZCLUCXCq.js b/assets/CurrentClass.html-ZCLUCXCq.js new file mode 100644 index 0000000..9ce5f8c --- /dev/null +++ b/assets/CurrentClass.html-ZCLUCXCq.js @@ -0,0 +1,16 @@ +import{_ as s,o as e,c as a,a as n}from"./app-Un_zyw_U.js";const o={},l=n(`在
countRange
区间 A ≤ this ≤ B。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class CurrentClass internal constructor(private val classSet: Class<*>, internal val instance: Any)
+
Change Records
v1.0.0
first
Function Illustrate
当前实例的类操作对象。
val name: String
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
classSet
的Class.getName
。
val simpleName: String
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
classSet
的Class.getSimpleName
。
fun generic(): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例中的泛型父类。
如果当前实例不存在泛型将返回 null
。
fun superClass(): SuperClass
+
Change Records
v1.0.0
first
Function Illustrate
调用父类实例。
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
Change Records
v1.0.0
first
Function Illustrate
调用当前实例中的变量。
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
Change Records
v1.0.0
first
Function Illustrate
调用当前实例中的方法。
inner class SuperClass internal constructor(private val superClassSet: Class<*>)
+
Change Records
v1.0.0
first
Function Illustrate
当前类的父类实例的类操作对象。
val name: String
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
classSet
中父类的Class.getName
。
val simpleName: String
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
classSet
中父类的Class.getSimpleName
。
fun generic(): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例父类中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例父类中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
Change Records
v1.0.0
first
Function Illustrate
调用父类实例中的变量。
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
Change Records
v1.0.0
first
Function Illustrate
`,95),t=[l];function p(c,r){return e(),a("div",null,t)}const i=s(o,[["render",p],["__file","CurrentClass.html.vue"]]);export{i as default}; diff --git a/assets/CurrentClass.html-aIvFMoGD.js b/assets/CurrentClass.html-aIvFMoGD.js new file mode 100644 index 0000000..786d4b6 --- /dev/null +++ b/assets/CurrentClass.html-aIvFMoGD.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-47f17664","path":"/en/api/public/com/highcapable/yukireflection/bean/CurrentClass.html","title":"CurrentClass - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"simpleName - field","slug":"simplename-field","link":"#simplename-field","children":[]},{"level":2,"title":"generic - method","slug":"generic-method","link":"#generic-method","children":[]},{"level":2,"title":"generic - method","slug":"generic-method-1","link":"#generic-method-1","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":2,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":2,"title":"SuperClass - class","slug":"superclass-class","link":"#superclass-class","children":[{"level":3,"title":"name - field","slug":"name-field-1","link":"#name-field-1","children":[]},{"level":3,"title":"simpleName - field","slug":"simplename-field-1","link":"#simplename-field-1","children":[]},{"level":3,"title":"generic - method","slug":"generic-method-2","link":"#generic-method-2","children":[]},{"level":3,"title":"generic - method","slug":"generic-method-3","link":"#generic-method-3","children":[]},{"level":3,"title":"field - method","slug":"field-method-1","link":"#field-method-1","children":[]},{"level":3,"title":"method - method","slug":"method-method-1","link":"#method-method-1","children":[]}]}],"git":{"updatedTime":1695808915000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/bean/CurrentClass.md"}');export{e as data}; diff --git a/assets/CurrentClass.html-iDLdKTRl.js b/assets/CurrentClass.html-iDLdKTRl.js new file mode 100644 index 0000000..ca23b71 --- /dev/null +++ b/assets/CurrentClass.html-iDLdKTRl.js @@ -0,0 +1,16 @@ +import{_ as s,o as a,c as e,a as n}from"./app-Un_zyw_U.js";const o={},l=n(`调用父类实例中的方法。
class CurrentClass internal constructor(private val classSet: Class<*>, internal val instance: Any)
+
变更记录
v1.0.0
添加
功能描述
当前实例的类操作对象。
val name: String
+
变更记录
v1.0.0
添加
功能描述
获得当前
classSet
的Class.getName
。
val simpleName: String
+
变更记录
v1.0.0
添加
功能描述
获得当前
classSet
的Class.getSimpleName
。
fun generic(): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前实例中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前实例中的泛型父类。
如果当前实例不存在泛型将返回 null
。
fun superClass(): SuperClass
+
变更记录
v1.0.0
添加
功能描述
调用父类实例。
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
变更记录
v1.0.0
添加
功能描述
调用当前实例中的变量。
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
变更记录
v1.0.0
添加
功能描述
调用当前实例中的方法。
inner class SuperClass internal constructor(private val superClassSet: Class<*>)
+
变更记录
v1.0.0
添加
功能描述
当前类的父类实例的类操作对象。
val name: String
+
变更记录
v1.0.0
添加
功能描述
获得当前
classSet
中父类的Class.getName
。
val simpleName: String
+
变更记录
v1.0.0
添加
功能描述
获得当前
classSet
中父类的Class.getSimpleName
。
fun generic(): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前实例父类中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前实例父类中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
变更记录
v1.0.0
添加
功能描述
调用父类实例中的变量。
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
变更记录
v1.0.0
添加
功能描述
`,94),p=[l];function c(t,r){return a(),e("div",null,p)}const i=s(o,[["render",c],["__file","CurrentClass.html.vue"]]);export{i as default}; diff --git a/assets/CurrentClass.html-sE3zJIrm.js b/assets/CurrentClass.html-sE3zJIrm.js new file mode 100644 index 0000000..9a341cd --- /dev/null +++ b/assets/CurrentClass.html-sE3zJIrm.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-406687ff","path":"/zh-cn/api/public/com/highcapable/yukireflection/bean/CurrentClass.html","title":"CurrentClass - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"simpleName - field","slug":"simplename-field","link":"#simplename-field","children":[]},{"level":2,"title":"generic - method","slug":"generic-method","link":"#generic-method","children":[]},{"level":2,"title":"generic - method","slug":"generic-method-1","link":"#generic-method-1","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":2,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":2,"title":"SuperClass - class","slug":"superclass-class","link":"#superclass-class","children":[{"level":3,"title":"name - field","slug":"name-field-1","link":"#name-field-1","children":[]},{"level":3,"title":"simpleName - field","slug":"simplename-field-1","link":"#simplename-field-1","children":[]},{"level":3,"title":"generic - method","slug":"generic-method-2","link":"#generic-method-2","children":[]},{"level":3,"title":"generic - method","slug":"generic-method-3","link":"#generic-method-3","children":[]},{"level":3,"title":"field - method","slug":"field-method-1","link":"#field-method-1","children":[]},{"level":3,"title":"method - method","slug":"method-method-1","link":"#method-method-1","children":[]}]}],"git":{"updatedTime":1695808915000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/bean/CurrentClass.md"}');export{e as data}; diff --git a/assets/DefinedTypeFactory.html-EYV1yl_b.js b/assets/DefinedTypeFactory.html-EYV1yl_b.js new file mode 100644 index 0000000..de5467e --- /dev/null +++ b/assets/DefinedTypeFactory.html-EYV1yl_b.js @@ -0,0 +1,2 @@ +import{_ as e,o as a,c as s,a as o}from"./app-Un_zyw_U.js";const t={},n=o(`调用父类实例中的方法。
变更记录
v1.0.0
添加
功能描述
这是一个内部类型的定义常量类,主要用于反射 API 相关用法的延伸。
val VagueType: Class<*>
+
变更记录
v1.0.0
添加
功能描述
`,11),c=[n];function p(d,r){return a(),s("div",null,c)}const i=e(t,[["render",p],["__file","DefinedTypeFactory.html.vue"]]);export{i as default}; diff --git a/assets/DefinedTypeFactory.html-IT5sdpCR.js b/assets/DefinedTypeFactory.html-IT5sdpCR.js new file mode 100644 index 0000000..ed8f6ac --- /dev/null +++ b/assets/DefinedTypeFactory.html-IT5sdpCR.js @@ -0,0 +1,2 @@ +import{_ as e,o as t,c as a,a as o}from"./app-Un_zyw_U.js";const s={},n=o(`得到模糊类型。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
这是一个内部类型的定义常量类,主要用于反射 API 相关用法的延伸。
val VagueType: Class<*>
+
Change Records
v1.0.0
first
Function Illustrate
`,12),c=[n];function r(l,p){return t(),a("div",null,c)}const d=e(s,[["render",r],["__file","DefinedTypeFactory.html.vue"]]);export{d as default}; diff --git a/assets/DefinedTypeFactory.html-OIQVLnGM.js b/assets/DefinedTypeFactory.html-OIQVLnGM.js new file mode 100644 index 0000000..73b190a --- /dev/null +++ b/assets/DefinedTypeFactory.html-OIQVLnGM.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-30e525ac","path":"/en/api/public/com/highcapable/yukireflection/type/defined/DefinedTypeFactory.html","title":"DefinedTypeFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"VagueType - field","slug":"vaguetype-field","link":"#vaguetype-field","children":[]}],"git":{"updatedTime":1674726569000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/type/defined/DefinedTypeFactory.md"}');export{e as data}; diff --git a/assets/DefinedTypeFactory.html-mINnsZd9.js b/assets/DefinedTypeFactory.html-mINnsZd9.js new file mode 100644 index 0000000..11e3934 --- /dev/null +++ b/assets/DefinedTypeFactory.html-mINnsZd9.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-597ac69b","path":"/zh-cn/api/public/com/highcapable/yukireflection/type/defined/DefinedTypeFactory.html","title":"DefinedTypeFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"VagueType - field","slug":"vaguetype-field","link":"#vaguetype-field","children":[]}],"git":{"updatedTime":1674666410000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/type/defined/DefinedTypeFactory.md"}');export{e as data}; diff --git a/assets/DexClassFinder.html-CuqfiW90.js b/assets/DexClassFinder.html-CuqfiW90.js new file mode 100644 index 0000000..79c4e67 --- /dev/null +++ b/assets/DexClassFinder.html-CuqfiW90.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-6d6cd473","path":"/en/api/public/com/highcapable/yukireflection/finder/classes/DexClassFinder.html","title":"DexClassFinder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"companion object - object","slug":"companion-object-object","link":"#companion-object-object","children":[{"level":3,"title":"clearCache - method","slug":"clearcache-method","link":"#clearcache-method","children":[]}]},{"level":2,"title":"fullName - field","slug":"fullname-field","link":"#fullname-field","children":[]},{"level":2,"title":"simpleName - field","slug":"simplename-field","link":"#simplename-field","children":[]},{"level":2,"title":"singleName - field","slug":"singlename-field","link":"#singlename-field","children":[]},{"level":2,"title":"from - method","slug":"from-method","link":"#from-method","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"fullName - method","slug":"fullname-method","link":"#fullname-method","children":[]},{"level":2,"title":"simpleName - method","slug":"simplename-method","link":"#simplename-method","children":[]},{"level":2,"title":"singleName - method","slug":"singlename-method","link":"#singlename-method","children":[]},{"level":2,"title":"fullName - method","slug":"fullname-method-1","link":"#fullname-method-1","children":[]},{"level":2,"title":"simpleName - method","slug":"simplename-method-1","link":"#simplename-method-1","children":[]},{"level":2,"title":"singleName - method","slug":"singlename-method-1","link":"#singlename-method-1","children":[]},{"level":2,"title":"extends - method","slug":"extends-method","link":"#extends-method","children":[]},{"level":2,"title":"extends - method","slug":"extends-method-1","link":"#extends-method-1","children":[]},{"level":2,"title":"implements - method","slug":"implements-method","link":"#implements-method","children":[]},{"level":2,"title":"implements - method","slug":"implements-method-1","link":"#implements-method-1","children":[]},{"level":2,"title":"anonymous - method","slug":"anonymous-method","link":"#anonymous-method","children":[]},{"level":2,"title":"noExtends - method","slug":"noextends-method","link":"#noextends-method","children":[]},{"level":2,"title":"noImplements - method","slug":"noimplements-method","link":"#noimplements-method","children":[]},{"level":2,"title":"noSuper - method","slug":"nosuper-method","link":"#nosuper-method","children":[]},{"level":2,"title":"enclosing - method","slug":"enclosing-method","link":"#enclosing-method","children":[]},{"level":2,"title":"enclosing - method","slug":"enclosing-method-1","link":"#enclosing-method-1","children":[]},{"level":2,"title":"FromPackageRules - class","slug":"frompackagerules-class","link":"#frompackagerules-class","children":[{"level":3,"title":"absolute - method","slug":"absolute-method","link":"#absolute-method","children":[]}]},{"level":2,"title":"ClassNameRules - class","slug":"classnamerules-class","link":"#classnamerules-class","children":[{"level":3,"title":"optional - method","slug":"optional-method","link":"#optional-method","children":[]}]},{"level":2,"title":"member - method","slug":"member-method","link":"#member-method","children":[]},{"level":2,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":2,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":2,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":2,"title":"Result - class","slug":"result-class","link":"#result-class","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"all - method","slug":"all-method-1","link":"#all-method-1","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"onNoClassDefFoundError - method","slug":"onnoclassdeffounderror-method","link":"#onnoclassdeffounderror-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]}]}],"git":{"updatedTime":1696178135000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/classes/DexClassFinder.md"}');export{e as data}; diff --git a/assets/DexClassFinder.html-UYJDQWR2.js b/assets/DexClassFinder.html-UYJDQWR2.js new file mode 100644 index 0000000..50e7af9 --- /dev/null +++ b/assets/DexClassFinder.html-UYJDQWR2.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-2d13d624","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/classes/DexClassFinder.html","title":"DexClassFinder - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"companion object - object","slug":"companion-object-object","link":"#companion-object-object","children":[{"level":3,"title":"clearCache - method","slug":"clearcache-method","link":"#clearcache-method","children":[]}]},{"level":2,"title":"fullName - field","slug":"fullname-field","link":"#fullname-field","children":[]},{"level":2,"title":"simpleName - field","slug":"simplename-field","link":"#simplename-field","children":[]},{"level":2,"title":"singleName - field","slug":"singlename-field","link":"#singlename-field","children":[]},{"level":2,"title":"from - method","slug":"from-method","link":"#from-method","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"fullName - method","slug":"fullname-method","link":"#fullname-method","children":[]},{"level":2,"title":"simpleName - method","slug":"simplename-method","link":"#simplename-method","children":[]},{"level":2,"title":"singleName - method","slug":"singlename-method","link":"#singlename-method","children":[]},{"level":2,"title":"fullName - method","slug":"fullname-method-1","link":"#fullname-method-1","children":[]},{"level":2,"title":"simpleName - method","slug":"simplename-method-1","link":"#simplename-method-1","children":[]},{"level":2,"title":"singleName - method","slug":"singlename-method-1","link":"#singlename-method-1","children":[]},{"level":2,"title":"extends - method","slug":"extends-method","link":"#extends-method","children":[]},{"level":2,"title":"extends - method","slug":"extends-method-1","link":"#extends-method-1","children":[]},{"level":2,"title":"implements - method","slug":"implements-method","link":"#implements-method","children":[]},{"level":2,"title":"implements - method","slug":"implements-method-1","link":"#implements-method-1","children":[]},{"level":2,"title":"anonymous - method","slug":"anonymous-method","link":"#anonymous-method","children":[]},{"level":2,"title":"noExtends - method","slug":"noextends-method","link":"#noextends-method","children":[]},{"level":2,"title":"noImplements - method","slug":"noimplements-method","link":"#noimplements-method","children":[]},{"level":2,"title":"noSuper - method","slug":"nosuper-method","link":"#nosuper-method","children":[]},{"level":2,"title":"enclosing - method","slug":"enclosing-method","link":"#enclosing-method","children":[]},{"level":2,"title":"enclosing - method","slug":"enclosing-method-1","link":"#enclosing-method-1","children":[]},{"level":2,"title":"FromPackageRules - class","slug":"frompackagerules-class","link":"#frompackagerules-class","children":[{"level":3,"title":"absolute - method","slug":"absolute-method","link":"#absolute-method","children":[]}]},{"level":2,"title":"ClassNameRules - class","slug":"classnamerules-class","link":"#classnamerules-class","children":[{"level":3,"title":"optional - method","slug":"optional-method","link":"#optional-method","children":[]}]},{"level":2,"title":"member - method","slug":"member-method","link":"#member-method","children":[]},{"level":2,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":2,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":2,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":2,"title":"Result - class","slug":"result-class","link":"#result-class","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"all - method","slug":"all-method-1","link":"#all-method-1","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"onNoClassDefFoundError - method","slug":"onnoclassdeffounderror-method","link":"#onnoclassdeffounderror-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]}]}],"git":{"updatedTime":1696178135000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/classes/DexClassFinder.md"}');export{e as data}; diff --git a/assets/DexClassFinder.html-oDUXm983.js b/assets/DexClassFinder.html-oDUXm983.js new file mode 100644 index 0000000..e27e7b6 --- /dev/null +++ b/assets/DexClassFinder.html-oDUXm983.js @@ -0,0 +1,46 @@ +import{_ as s,o as e,c as a,a as o}from"./app-Un_zyw_U.js";const n={},l=o(`得到模糊类型。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class DexClassFinder internal constructor(
+ private val context: Context?,
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
Class
查找类。
可使用 BaseDexClassLoader
通过指定条件查找指定 Class
或一组 Class
。
Notice
此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
Change Records
v1.0.0
first
fun clearCache(context: Context, versionName: String?, versionCode: Long?)
+
Change Records
v1.0.0
first
Function Illustrate
清除当前
DexClassFinder
的Class
缓存。
适用于全部通过 ClassLoader.searchClass 获取的 DexClassFinder
。
var fullName: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
完整名称。
只会查找匹配到的 Class.getName
。
例如 com.demo.Test
需要填写 com.demo.Test
。
var simpleName: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
简单名称。
只会查找匹配到的 Class.getSimpleName
。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
会为空,此时你可以使用 singleName。
var singleName: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
独立名称。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。
fun from(vararg name: String): FromPackageRules
+
Change Records
v1.0.0
first
Function Illustrate
设置在指定包名范围查找当前
Class
。
设置后仅会在当前 name
开头匹配的包名路径下进行查找,可提升查找速度。
例如 ↓
com.demo.test
com.demo.test.demo
Notice
建议设置此参数指定查找范围,否则 Class 过多时将会非常慢。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
标识符筛选条件。
可不设置筛选条件。
fun fullName(value: String): ClassNameRules
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
完整名称。
只会查找匹配到的 Class.getName
。
例如 com.demo.Test
需要填写 com.demo.Test
。
fun simpleName(value: String): ClassNameRules
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
简单名称。
只会查找匹配到的 Class.getSimpleName
。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest 会为空
,此时你可以使用 singleName。
fun singleName(value: String): ClassNameRules
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
独立名称。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。
fun fullName(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
完整名称条件。
只会查找匹配到的 Class.getName
。
fun simpleName(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
简单名称条件。
只会查找匹配到的 Class.getSimpleName
。
fun singleName(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
独立名称条件。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
inline fun <reified T> extends()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
继承的父类。
fun extends(vararg name: String)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
继承的父类。
会同时查找 name
中所有匹配的父类。
inline fun <reified T> implements()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
实现的接口类。
fun implements(vararg name: String)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
实现的接口类。
会同时查找 name
中所有匹配的接口类。
fun anonymous()
+
Change Records
v1.0.0
first
Function Illustrate
标识
Class
为匿名类。
例如 com.demo.Test$1
或 com.demo.Test$InnerTest
。
标识后你可以使用 enclosing 来进一步指定匿名类的 (封闭类) 主类。
fun noExtends()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
没有任何继承。
此时 Class
只应该继承于 Any
。
Notice
设置此条件后 extends 将失效。
fun noImplements()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
没有任何接口。
Notice
设置此条件后 implements 将失效。
fun noSuper()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
没有任何继承与接口。
此时 Class
只应该继承于 Any
。
Notice
设置此条件后 extends 与 implements 将失效。
inline fun <reified T> enclosing()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
匿名类的 (封闭类) 主类。
fun enclosing(vararg name: String)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
匿名类的 (封闭类) 主类。
会同时查找 name
中所有匹配的 (封闭类) 主类。
inner class FromPackageRules internal constructor(private val packages: MutableList<ClassRulesData.PackageRulesData>)
+
Change Records
v1.0.0
first
Function Illustrate
包名范围名称过滤匹配条件实现类。
fun absolute()
+
Change Records
v1.0.0
first
Function Illustrate
设置包名绝对匹配。
例如有如下包名 ↓
com.demo.test.a
com.demo.test.a.b
com.demo.test.active
若包名条件为 com.demo.test.a
则绝对匹配仅能匹配到第一个。
相反地,不设置以上示例会全部匹配。
inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
+
Change Records
v1.0.0
first
Function Illustrate
类名匹配条件实现类。
fun optional()
+
Change Records
v1.0.0
first
Function Illustrate
设置类名可选。
例如有如下类名 ↓
com.demo.Test
fullName / Test
simpleName
defpackage.a
fullName / a
simpleName
这两个类名都是同一个类,但是在有些版本中被混淆有些版本没有。
此时可设置类名为 com.demo.Test
fullName / Test
simpleName。
这样就可在完全匹配类名情况下使用类名而忽略其它查找条件,否则忽略此条件继续使用其它查找条件。
inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
满足的Member
条件。
inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
满足的Field
条件。
inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
满足的Method
条件。
inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
满足的Constructor
条件。
inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
+
Change Records
v1.0.0
first
Function Illustrate
Class
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建监听结果事件方法体。
fun get(): Class<*>?
+
Change Records
v1.0.0
first
Function Illustrate
得到
Class
本身。
若有多个 Class
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
若你设置了 async
请使用 wait 方法。
fun all(): MutableList<Class<*>>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Class
本身数组。
返回全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
若你设置了 async
请使用 waitAll 方法。
fun all(result: (Class<*>) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
得到
Class
本身数组 (依次遍历)。
回调全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将不会执行。
若你设置了 async
请使用 waitAll 方法。
fun wait(result: (Class<*>?) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
得到
Class
本身 (异步)。
若有多个 Class
结果只会回调第一个。
在查找条件找不到任何结果的时候将回调 null。
你需要设置 async
后此方法才会被回调,否则请使用 get 方法。
fun waitAll(result: (MutableList<Class<*>>) -> Unit): Result
+
Change Records
v1.0.0
first
v1.0.3
modified
result
类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Class
本身数组 (异步)。
回调全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将回调空的 MutableList
。
你需要设置 async
后此方法才会被回调,否则请使用 all 方法。
fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
监听找不到
Class
时。
fun ignored(): Result
+
Change Records
v1.0.0
first
Function Illustrate
忽略异常并停止打印任何错误日志。
此时若要监听异常结果,你需要手动实现 onNoClassDefFoundError 方法。
`,314),t=[l];function p(c,r){return e(),a("div",null,t)}const i=s(n,[["render",p],["__file","DexClassFinder.html.vue"]]);export{i as default}; diff --git a/assets/DexClassFinder.html-tnGJIsCX.js b/assets/DexClassFinder.html-tnGJIsCX.js new file mode 100644 index 0000000..8f46d7c --- /dev/null +++ b/assets/DexClassFinder.html-tnGJIsCX.js @@ -0,0 +1,46 @@ +import{_ as s,o as e,c as a,a as o}from"./app-Un_zyw_U.js";const n={},l=o(`class DexClassFinder internal constructor(
+ private val context: Context?,
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder
+
变更记录
v1.0.0
添加
功能描述
Class
查找类。
可使用 BaseDexClassLoader
通过指定条件查找指定 Class
或一组 Class
。
注意
此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
变更记录
v1.0.0
添加
fun clearCache(context: Context, versionName: String?, versionCode: Long?)
+
变更记录
v1.0.0
添加
功能描述
清除当前
DexClassFinder
的Class
缓存。
适用于全部通过 ClassLoader.searchClass 获取的 DexClassFinder
。
var fullName: String
+
变更记录
v1.0.0
添加
功能描述
设置
Class
完整名称。
只会查找匹配到的 Class.getName
。
例如 com.demo.Test
需要填写 com.demo.Test
。
var simpleName: String
+
变更记录
v1.0.0
添加
功能描述
设置
Class
简单名称。
只会查找匹配到的 Class.getSimpleName
。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
会为空,此时你可以使用 singleName。
var singleName: String
+
变更记录
v1.0.0
添加
功能描述
设置
Class
独立名称。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。
fun from(vararg name: String): FromPackageRules
+
变更记录
v1.0.0
添加
功能描述
设置在指定包名范围查找当前
Class
。
设置后仅会在当前 name
开头匹配的包名路径下进行查找,可提升查找速度。
例如 ↓
com.demo.test
com.demo.test.demo
注意
建议设置此参数指定查找范围,否则 Class 过多时将会非常慢。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
标识符筛选条件。
可不设置筛选条件。
fun fullName(value: String): ClassNameRules
+
变更记录
v1.0.0
添加
功能描述
设置
Class
完整名称。
只会查找匹配到的 Class.getName
。
例如 com.demo.Test
需要填写 com.demo.Test
。
fun simpleName(value: String): ClassNameRules
+
变更记录
v1.0.0
添加
功能描述
设置
Class
简单名称。
只会查找匹配到的 Class.getSimpleName
。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest 会为空
,此时你可以使用 singleName。
fun singleName(value: String): ClassNameRules
+
变更记录
v1.0.0
添加
功能描述
设置
Class
独立名称。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。
fun fullName(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
完整名称条件。
只会查找匹配到的 Class.getName
。
fun simpleName(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
简单名称条件。
只会查找匹配到的 Class.getSimpleName
。
fun singleName(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
独立名称条件。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
inline fun <reified T> extends()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
继承的父类。
fun extends(vararg name: String)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
继承的父类。
会同时查找 name
中所有匹配的父类。
inline fun <reified T> implements()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
实现的接口类。
fun implements(vararg name: String)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
实现的接口类。
会同时查找 name
中所有匹配的接口类。
fun anonymous()
+
变更记录
v1.0.0
添加
功能描述
标识
Class
为匿名类。
例如 com.demo.Test$1
或 com.demo.Test$InnerTest
。
标识后你可以使用 enclosing 来进一步指定匿名类的 (封闭类) 主类。
fun noExtends()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
没有任何继承。
此时 Class
只应该继承于 Any
。
注意
设置此条件后 extends 将失效。
fun noImplements()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
没有任何接口。
注意
设置此条件后 implements 将失效。
fun noSuper()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
没有任何继承与接口。
此时 Class
只应该继承于 Any
。
注意
设置此条件后 extends 与 implements 将失效。
inline fun <reified T> enclosing()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
匿名类的 (封闭类) 主类。
fun enclosing(vararg name: String)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
匿名类的 (封闭类) 主类。
会同时查找 name
中所有匹配的 (封闭类) 主类。
inner class FromPackageRules internal constructor(private val packages: MutableList<ClassRulesData.PackageRulesData>)
+
变更记录
v1.0.0
添加
功能描述
包名范围名称过滤匹配条件实现类。
fun absolute()
+
变更记录
v1.0.0
添加
功能描述
设置包名绝对匹配。
例如有如下包名 ↓
com.demo.test.a
com.demo.test.a.b
com.demo.test.active
若包名条件为 com.demo.test.a
则绝对匹配仅能匹配到第一个。
相反地,不设置以上示例会全部匹配。
inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
+
变更记录
v1.0.0
添加
功能描述
类名匹配条件实现类。
fun optional()
+
变更记录
v1.0.0
添加
功能描述
设置类名可选。
例如有如下类名 ↓
com.demo.Test
fullName / Test
simpleName
defpackage.a
fullName / a
simpleName
这两个类名都是同一个类,但是在有些版本中被混淆有些版本没有。
此时可设置类名为 com.demo.Test
fullName / Test
simpleName。
这样就可在完全匹配类名情况下使用类名而忽略其它查找条件,否则忽略此条件继续使用其它查找条件。
inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置
Class
满足的Member
条件。
inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置
Class
满足的Field
条件。
inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置
Class
满足的Method
条件。
inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置
Class
满足的Constructor
条件。
inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
+
变更记录
v1.0.0
添加
功能描述
Class
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建监听结果事件方法体。
fun get(): Class<*>?
+
变更记录
v1.0.0
添加
功能描述
得到
Class
本身。
若有多个 Class
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
若你设置了 async
请使用 wait 方法。
fun all(): MutableList<Class<*>>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
功能描述
得到
Class
本身数组。
返回全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
若你设置了 async
请使用 waitAll 方法。
fun all(result: (Class<*>) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
得到
Class
本身数组 (依次遍历)。
回调全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将不会执行。
若你设置了 async
请使用 waitAll 方法。
fun wait(result: (Class<*>?) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
得到
Class
本身 (异步)。
若有多个 Class
结果只会回调第一个。
在查找条件找不到任何结果的时候将回调 null。
你需要设置 async
后此方法才会被回调,否则请使用 get 方法。
fun waitAll(result: (MutableList<Class<*>>) -> Unit): Result
+
变更记录
v1.0.0
添加
v1.0.3
修改
result
类型由 HashSet
修改为 MutableList
功能描述
得到
Class
本身数组 (异步)。
回调全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将回调空的 MutableList
。
你需要设置 async
后此方法才会被回调,否则请使用 all 方法。
fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
监听找不到
Class
时。
fun ignored(): Result
+
变更记录
v1.0.0
添加
功能描述
忽略异常并停止打印任何错误日志。
此时若要监听异常结果,你需要手动实现 onNoClassDefFoundError 方法。
`,313),p=[l];function c(t,d){return e(),a("div",null,p)}const i=s(n,[["render",c],["__file","DexClassFinder.html.vue"]]);export{i as default}; diff --git a/assets/FieldFinder.html-CaQR3qZR.js b/assets/FieldFinder.html-CaQR3qZR.js new file mode 100644 index 0000000..71c6005 --- /dev/null +++ b/assets/FieldFinder.html-CaQR3qZR.js @@ -0,0 +1,84 @@ +import{_ as s,o as n,c as e,a}from"./app-Un_zyw_U.js";const o={},l=a(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class FieldFinder internal constructor(override val classSet: Class<*>?) : MemberBaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
Field
查找类。
可通过指定类型查找指定 Field
或一组 Field
。
var name: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称。
Pay Attention
若不填写名称则必须存在一个其它条件。
var type: Any?
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型。
可不填写类型。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
标识符筛选条件。
可不设置筛选条件。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun order(): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
顺序筛选字节码的下标。
fun name(value: String): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称。
Pay Attention
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun name(conditions: NameConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称条件。
Pay Attention
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun type(value: Any): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型。
可不填写类型。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun type(conditions: ObjectConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型条件。
可不填写类型。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
Change Records
v1.0.0
first
Function Illustrate
设置在
classSet
的所有父类中查找当前Field
。
Notice
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
Field
重查找实现类,可累计失败次数直到查找成功。
inline fun field(initiate: FieldConditions): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建需要重新查找的
Field
。
你可以添加多个备选 Field
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Field>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
modified
initiate
类型由 HashSet
修改为 MutableList
Function Illustrate
当在
RemedyPlan
中找到结果时。
Function Example
你可以方便地对重查找的 Field
实现 onFind
方法。
The following example
field {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
Change Records
v1.0.0
first
Function Illustrate
Field
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建监听结果事件方法体。
Function Example
你可以使用 lambda 形式创建 Result
类。
The following example
field {
+ // Your code here.
+}.result {
+ get(instance).set("something")
+ get(instance).string()
+ get(instance).cast<CustomClass>()
+ get().boolean()
+ all(instance)
+ give()
+ giveAll()
+ onNoSuchField {}
+}
+
fun get(instance: Any?): Instance
+
Change Records
v1.0.0
first
Function Illustrate
获得
Field
实例处理类。
若有多个 Field
结果只会返回第一个。
Function Example
你可以轻松地得到 Field
的实例以及使用它进行设置实例。
The following example
field {
+ // Your code here.
+}.get(instance).set("something")
+
如果你取到的是静态 Field
,可以不需要设置实例。
The following example
field {
+ // Your code here.
+}.get().set("something")
+
fun all(instance: Any?): MutableList<Instance>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Field
实例处理类数组。
返回全部查找条件匹配的多个 Field
实例结果。
Function Example
你可以通过此方法来获得当前条件结果中匹配的全部 Field
,其 Field
所在实例用法与 get
相同。
The following example
field {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.self
+}
+
fun give(): Field?
+
Change Records
v1.0.0
first
Function Illustrate
得到
Field
本身。
若有多个 Field 结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Field>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Field
本身数组。
返回全部查找条件匹配的多个 Field
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
获得
Field
实例处理类,配合RemedyPlan
使用。
若有多个 Field
结果只会返回第一个。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(instance: Any?, initiate: MutableList<Instance>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
modified
initiate
类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Field
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Field
实例结果。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建
Field
重查找功能。
Function Example
当你遇到一种 Field
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchField
捕获异常二次查找 Field
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
The following example
field {
+ // Your code here.
+}.remedys {
+ field {
+ // Your code here.
+ }
+ field {
+ // Your code here.
+ }
+}
+
fun onNoSuchField(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
监听找不到
Field
时。
fun ignored(): Result
+
Change Records
v1.0.0
first
Function Illustrate
忽略异常并停止打印任何错误日志。
Notice
此时若要监听异常结果,你需要手动实现 onNoSuchField 方法。
inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
+
Change Records
v1.0.0
first
Function Illustrate
Field
实例变量处理类。
fun current(ignored: Boolean): CurrentClass?
+
inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
Field
自身self
实例的类操作对象CurrentClass
。
fun <T> cast(): T?
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
实例。
fun byte(): Byte?
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Byte 实例。
fun int(): Int
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Int 实例。
fun long(): Long
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Long 实例。
fun short(): Short
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Short 实例。
fun double(): Double
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Double 实例。
fun float(): Float
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Float 实例。
fun string(): String
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
String 实例。
fun char(): Char
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Char 实例。
fun boolean(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Boolean 实例。
fun any(): Any?
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Any 实例。
inline fun <reified T> array(): Array<T>
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Array 实例。
inline fun <reified T> list(): List<T>
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
List 实例。
fun set(any: Any?)
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Field
实例。
fun setTrue()
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Field
实例为true
。
Pay Attention
请确保实例对象类型为 Boolean。
fun setFalse()
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Field
实例为false
。
Pay Attention
请确保实例对象类型为 Boolean。
fun setNull()
+
Change Records
v1.0.0
first
Function Illustrate
`,324),t=[l];function p(c,r){return n(),e("div",null,t)}const i=s(o,[["render",p],["__file","FieldFinder.html.vue"]]);export{i as default}; diff --git a/assets/FieldFinder.html-SCPPTVS5.js b/assets/FieldFinder.html-SCPPTVS5.js new file mode 100644 index 0000000..a375830 --- /dev/null +++ b/assets/FieldFinder.html-SCPPTVS5.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-4b907076","path":"/en/api/public/com/highcapable/yukireflection/finder/members/FieldFinder.html","title":"FieldFinder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"type - field","slug":"type-field","link":"#type-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"order - method","slug":"order-method","link":"#order-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"name - method","slug":"name-method-1","link":"#name-method-1","children":[]},{"level":2,"title":"type - method","slug":"type-method","link":"#type-method","children":[]},{"level":2,"title":"type - method","slug":"type-method-1","link":"#type-method-1","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchField - method","slug":"onnosuchfield-method","link":"#onnosuchfield-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]}]}],"git":{"updatedTime":1696172435000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":5}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/members/FieldFinder.md"}');export{e as data}; diff --git a/assets/FieldFinder.html-_oWPO7Eh.js b/assets/FieldFinder.html-_oWPO7Eh.js new file mode 100644 index 0000000..43d0dd5 --- /dev/null +++ b/assets/FieldFinder.html-_oWPO7Eh.js @@ -0,0 +1,84 @@ +import{_ as s,o as a,c as n,a as e}from"./app-Un_zyw_U.js";const o={},l=e(`设置当前
Field
实例为null
。
class FieldFinder internal constructor(override val classSet: Class<*>?) : MemberBaseFinder
+
变更记录
v1.0.0
添加
功能描述
Field
查找类。
可通过指定类型查找指定 Field
或一组 Field
。
var name: String
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称。
特别注意
若不填写名称则必须存在一个其它条件。
var type: Any?
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型。
可不填写类型。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
标识符筛选条件。
可不设置筛选条件。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun order(): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
顺序筛选字节码的下标。
fun name(value: String): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称。
特别注意
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun name(conditions: NameConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称条件。
特别注意
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun type(value: Any): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型。
可不填写类型。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun type(conditions: ObjectConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型条件。
可不填写类型。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
变更记录
v1.0.0
添加
功能描述
设置在
classSet
的所有父类中查找当前Field
。
注意
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
变更记录
v1.0.0
添加
功能描述
Field
重查找实现类,可累计失败次数直到查找成功。
inline fun field(initiate: FieldConditions): Result
+
变更记录
v1.0.0
添加
功能描述
创建需要重新查找的
Field
。
你可以添加多个备选 Field
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
变更记录
v1.0.0
添加
功能描述
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Field>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 HashSet
修改为 MutableList
功能描述
当在
RemedyPlan
中找到结果时。
功能示例
你可以方便地对重查找的 Field
实现 onFind
方法。
示例如下
field {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
变更记录
v1.0.0
添加
功能描述
Field
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建监听结果事件方法体。
功能示例
你可以使用 lambda 形式创建 Result
类。
示例如下
field {
+ // Your code here.
+}.result {
+ get(instance).set("something")
+ get(instance).string()
+ get(instance).cast<CustomClass>()
+ get().boolean()
+ all(instance)
+ give()
+ giveAll()
+ onNoSuchField {}
+}
+
fun get(instance: Any?): Instance
+
变更记录
v1.0.0
添加
功能描述
获得
Field
实例处理类。
若有多个 Field
结果只会返回第一个。
功能示例
你可以轻松地得到 Field
的实例以及使用它进行设置实例。
示例如下
field {
+ // Your code here.
+}.get(instance).set("something")
+
如果你取到的是静态 Field
,可以不需要设置实例。
示例如下
field {
+ // Your code here.
+}.get().set("something")
+
fun all(instance: Any?): MutableList<Instance>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 ArrayList
修改为 MutableList
功能描述
获得
Field
实例处理类数组。
返回全部查找条件匹配的多个 Field
实例结果。
功能示例
你可以通过此方法来获得当前条件结果中匹配的全部 Field
,其 Field
所在实例用法与 get
相同。
示例如下
field {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.self
+}
+
fun give(): Field?
+
变更记录
v1.0.0
添加
功能描述
得到
Field
本身。
若有多个 Field 结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Field>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
功能描述
得到
Field
本身数组。
返回全部查找条件匹配的多个 Field
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
变更记录
v1.0.0
添加
功能描述
获得
Field
实例处理类,配合RemedyPlan
使用。
若有多个 Field
结果只会返回第一个。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(instance: Any?, initiate: MutableList<Instance>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 ArrayList
修改为 MutableList
功能描述
获得
Field
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Field
实例结果。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建
Field
重查找功能。
功能示例
当你遇到一种 Field
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchField
捕获异常二次查找 Field
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
示例如下
field {
+ // Your code here.
+}.remedys {
+ field {
+ // Your code here.
+ }
+ field {
+ // Your code here.
+ }
+}
+
fun onNoSuchField(result: (Throwable) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
监听找不到
Field
时。
fun ignored(): Result
+
变更记录
v1.0.0
添加
功能描述
忽略异常并停止打印任何错误日志。
注意
此时若要监听异常结果,你需要手动实现 onNoSuchField 方法。
inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
+
变更记录
v1.0.0
添加
功能描述
Field
实例变量处理类。
fun current(ignored: Boolean): CurrentClass?
+
inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
+
变更记录
v1.0.0
添加
功能描述
获得当前
Field
自身self
实例的类操作对象CurrentClass
。
fun <T> cast(): T?
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
实例。
fun byte(): Byte?
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Byte 实例。
fun int(): Int
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Int 实例。
fun long(): Long
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Long 实例。
fun short(): Short
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Short 实例。
fun double(): Double
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Double 实例。
fun float(): Float
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Float 实例。
fun string(): String
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
String 实例。
fun char(): Char
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Char 实例。
fun boolean(): Boolean
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Boolean 实例。
fun any(): Any?
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Any 实例。
inline fun <reified T> array(): Array<T>
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Array 实例。
inline fun <reified T> list(): List<T>
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
List 实例。
fun set(any: Any?)
+
变更记录
v1.0.0
添加
功能描述
设置当前
Field
实例。
fun setTrue()
+
变更记录
v1.0.0
添加
功能描述
设置当前
Field
实例为true
。
特别注意
请确保实例对象类型为 Boolean。
fun setFalse()
+
变更记录
v1.0.0
添加
功能描述
设置当前
Field
实例为false
。
特别注意
请确保实例对象类型为 Boolean。
fun setNull()
+
变更记录
v1.0.0
添加
功能描述
`,323),p=[l];function t(c,d){return a(),n("div",null,p)}const i=s(o,[["render",t],["__file","FieldFinder.html.vue"]]);export{i as default}; diff --git a/assets/FieldFinder.html-zKtt89hV.js b/assets/FieldFinder.html-zKtt89hV.js new file mode 100644 index 0000000..323f215 --- /dev/null +++ b/assets/FieldFinder.html-zKtt89hV.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-293ae898","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/members/FieldFinder.html","title":"FieldFinder - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"type - field","slug":"type-field","link":"#type-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"order - method","slug":"order-method","link":"#order-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"name - method","slug":"name-method-1","link":"#name-method-1","children":[]},{"level":2,"title":"type - method","slug":"type-method","link":"#type-method","children":[]},{"level":2,"title":"type - method","slug":"type-method-1","link":"#type-method-1","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchField - method","slug":"onnosuchfield-method","link":"#onnosuchfield-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]}]}],"git":{"updatedTime":1696172435000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/members/FieldFinder.md"}');export{e as data}; diff --git a/assets/FieldRules.html-IMr78QcL.js b/assets/FieldRules.html-IMr78QcL.js new file mode 100644 index 0000000..32e69a7 --- /dev/null +++ b/assets/FieldRules.html-IMr78QcL.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-30993156","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/FieldRules.html","title":"FieldRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"type - field","slug":"type-field","link":"#type-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"type - method","slug":"type-method","link":"#type-method","children":[]}],"git":{"updatedTime":1695808915000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/FieldRules.md"}');export{e as data}; diff --git a/assets/FieldRules.html-J5ZPIA8O.js b/assets/FieldRules.html-J5ZPIA8O.js new file mode 100644 index 0000000..d91006d --- /dev/null +++ b/assets/FieldRules.html-J5ZPIA8O.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-82a85036","path":"/en/api/public/com/highcapable/yukireflection/finder/classes/rules/FieldRules.html","title":"FieldRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"type - field","slug":"type-field","link":"#type-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"type - method","slug":"type-method","link":"#type-method","children":[]}],"git":{"updatedTime":1695808915000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/classes/rules/FieldRules.md"}');export{e as data}; diff --git a/assets/FieldRules.html-m_-yonQY.js b/assets/FieldRules.html-m_-yonQY.js new file mode 100644 index 0000000..0451d8e --- /dev/null +++ b/assets/FieldRules.html-m_-yonQY.js @@ -0,0 +1,7 @@ +import{_ as s,o as e,c as a,a as o}from"./app-Un_zyw_U.js";const n={},l=o(`设置当前
Field
实例为null
。
class FieldRules internal constructor(private val rulesData: FieldRulesData) : BaseRules
+
变更记录
v1.0.0
添加
功能描述
Field
查找条件实现类。
var name: String
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称。
var type: Any?
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型。
可不填写类型。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Field
标识符筛选条件。
可不设置筛选条件。
fun name(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称条件。
fun type(conditions: ObjectConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型条件。
可不填写类型。
`,39),p=[l];function c(t,d){return e(),a("div",null,p)}const i=s(n,[["render",c],["__file","FieldRules.html.vue"]]);export{i as default}; diff --git a/assets/FieldRules.html-tbZ9y4HH.js b/assets/FieldRules.html-tbZ9y4HH.js new file mode 100644 index 0000000..34577f7 --- /dev/null +++ b/assets/FieldRules.html-tbZ9y4HH.js @@ -0,0 +1,7 @@ +import{_ as s,o as e,c as a,a as o}from"./app-Un_zyw_U.js";const n={},l=o(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class FieldRules internal constructor(private val rulesData: FieldRulesData) : BaseRules
+
Change Records
v1.0.0
first
Function Illustrate
Field
查找条件实现类。
var name: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称。
var type: Any?
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型。
可不填写类型。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
标识符筛选条件。
可不设置筛选条件。
fun name(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称条件。
fun type(conditions: ObjectConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型条件。
可不填写类型。
`,40),t=[l];function c(p,r){return e(),a("div",null,t)}const i=s(n,[["render",c],["__file","FieldRules.html.vue"]]);export{i as default}; diff --git a/assets/GenericClass.html--Lql8mDe.js b/assets/GenericClass.html--Lql8mDe.js new file mode 100644 index 0000000..6c0b167 --- /dev/null +++ b/assets/GenericClass.html--Lql8mDe.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-38df33ac","path":"/en/api/public/com/highcapable/yukireflection/bean/GenericClass.html","title":"GenericClass - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"argument - method","slug":"argument-method","link":"#argument-method","children":[]}],"git":{"updatedTime":1696093225000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/bean/GenericClass.md"}');export{e as data}; diff --git a/assets/GenericClass.html-TJqKXlog.js b/assets/GenericClass.html-TJqKXlog.js new file mode 100644 index 0000000..0ed2ef0 --- /dev/null +++ b/assets/GenericClass.html-TJqKXlog.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-c5831246","path":"/zh-cn/api/public/com/highcapable/yukireflection/bean/GenericClass.html","title":"GenericClass - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"argument - method","slug":"argument-method","link":"#argument-method","children":[]}],"git":{"updatedTime":1696093225000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/bean/GenericClass.md"}');export{e as data}; diff --git a/assets/GenericClass.html-VZQ2Br0U.js b/assets/GenericClass.html-VZQ2Br0U.js new file mode 100644 index 0000000..9186975 --- /dev/null +++ b/assets/GenericClass.html-VZQ2Br0U.js @@ -0,0 +1,4 @@ +import{_ as s,o as a,c as n,a as e}from"./app-Un_zyw_U.js";const o={},l=e(`class GenericClass internal constructor(private val type: ParameterizedType)
+
变更记录
v1.0.0
添加
功能描述
当前
Class
的泛型父类操作对象。
fun argument(index: Int): Class<*>?
+
inline fun <reified T> argument(index: Int): Class<T>?
+
变更记录
v1.0.0
添加
v1.0.3
修改
方法的返回值可为 null
功能描述
获得泛型参数数组下标的
Class
实例。
注意
在运行时局部变量的泛型会被擦除,获取不到时将会返回 null。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class GenericClass internal constructor(private val type: ParameterizedType)
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
的泛型父类操作对象。
fun argument(index: Int): Class<*>?
+
inline fun <reified T> argument(index: Int): Class<T>?
+
Change Records
v1.0.0
first
v1.0.3
modified
方法的返回值可为 null
Function Illustrate
获得泛型参数数组下标的
Class
实例。
Notice
在运行时局部变量的泛型会被擦除,获取不到时将会返回 null。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
',6),d={href:"https://github.com/HighCapable/YukiReflection/blob/master/yukireflection/src/main/java/com/highcapable/yukireflection/type/android/GraphicsTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"};function h(u,f){const o=r("ExternalLinkIcon");return c(),n("div",null,[l,t("p",null,[e("详情可 "),t("a",d,[e("点击这里"),s(o)]),e(" 进行查看。")])])}const g=a(p,[["render",h],["__file","GraphicsTypeFactory.html.vue"]]);export{g as default}; diff --git a/assets/GraphicsTypeFactory.html-LLClnUt2.js b/assets/GraphicsTypeFactory.html-LLClnUt2.js new file mode 100644 index 0000000..95b543d --- /dev/null +++ b/assets/GraphicsTypeFactory.html-LLClnUt2.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-25cdee85","path":"/zh-cn/api/public/com/highcapable/yukireflection/type/android/GraphicsTypeFactory.html","title":"GraphicsTypeFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[],"git":{"updatedTime":1696445455000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/type/android/GraphicsTypeFactory.md"}');export{e as data}; diff --git a/assets/GraphicsTypeFactory.html-xL-hvwWg.js b/assets/GraphicsTypeFactory.html-xL-hvwWg.js new file mode 100644 index 0000000..33e95a0 --- /dev/null +++ b/assets/GraphicsTypeFactory.html-xL-hvwWg.js @@ -0,0 +1 @@ +import{_ as c,r as t,o as r,c as n,b as o,d as e,e as s,a as p}from"./app-Un_zyw_U.js";const i={},d=p('这是一个预置反射类型的常量类,主要为
Android
相关Graphics
的Class
内容,跟随版本更新会逐一进行增加。
变更记录
v1.0.0
添加
功能描述
',5),l={href:"https://github.com/HighCapable/YukiReflection/blob/master/yukireflection/src/main/java/com/highcapable/yukireflection/type/android/GraphicsTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"};function h(_,y){const a=t("ExternalLinkIcon");return r(),n("div",null,[d,o("p",null,[e("详情可 "),o("a",l,[e("点击这里"),s(a)]),e(" 进行查看。")])])}const k=c(i,[["render",h],["__file","GraphicsTypeFactory.html.vue"]]);export{k as default}; diff --git a/assets/MemberRules.html-1gLEBvW8.js b/assets/MemberRules.html-1gLEBvW8.js new file mode 100644 index 0000000..3eda97f --- /dev/null +++ b/assets/MemberRules.html-1gLEBvW8.js @@ -0,0 +1,3 @@ +import{_ as s,o as e,c as a,a as o}from"./app-Un_zyw_U.js";const n={},l=o(`这是一个预置反射类型的常量类,主要为
Android
相关Graphics
的Class
内容,跟随版本更新会逐一进行增加。
class MemberRules internal constructor(private val rulesData: MemberRulesData) : BaseRules
+
变更记录
v1.0.0
添加
功能描述
Member
查找条件实现类。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Member
标识符筛选条件。
可不设置筛选条件。
`,13),c=[l];function r(t,p){return e(),a("div",null,c)}const i=s(n,[["render",r],["__file","MemberRules.html.vue"]]);export{i as default}; diff --git a/assets/MemberRules.html-cNDASndV.js b/assets/MemberRules.html-cNDASndV.js new file mode 100644 index 0000000..10f1486 --- /dev/null +++ b/assets/MemberRules.html-cNDASndV.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-3daa8d42","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/MemberRules.html","title":"MemberRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]}],"git":{"updatedTime":1695808915000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/MemberRules.md"}');export{e as data}; diff --git a/assets/MemberRules.html-s0L0dO7U.js b/assets/MemberRules.html-s0L0dO7U.js new file mode 100644 index 0000000..c740552 --- /dev/null +++ b/assets/MemberRules.html-s0L0dO7U.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-71ecb893","path":"/en/api/public/com/highcapable/yukireflection/finder/classes/rules/MemberRules.html","title":"MemberRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]}],"git":{"updatedTime":1695808915000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/classes/rules/MemberRules.md"}');export{e as data}; diff --git a/assets/MemberRules.html-wPy0xHct.js b/assets/MemberRules.html-wPy0xHct.js new file mode 100644 index 0000000..ad58281 --- /dev/null +++ b/assets/MemberRules.html-wPy0xHct.js @@ -0,0 +1,3 @@ +import{_ as s,o as e,c as o,a}from"./app-Un_zyw_U.js";const n={},t=a(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MemberRules internal constructor(private val rulesData: MemberRulesData) : BaseRules
+
Change Records
v1.0.0
first
Function Illustrate
Member
查找条件实现类。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Member
标识符筛选条件。
可不设置筛选条件。
`,14),l=[t];function r(c,p){return e(),o("div",null,l)}const d=s(n,[["render",r],["__file","MemberRules.html.vue"]]);export{d as default}; diff --git a/assets/MemberRulesResult.html-2SlL_c8V.js b/assets/MemberRulesResult.html-2SlL_c8V.js new file mode 100644 index 0000000..400b544 --- /dev/null +++ b/assets/MemberRulesResult.html-2SlL_c8V.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-4f47dfda","path":"/en/api/public/com/highcapable/yukireflection/finder/classes/rules/result/MemberRulesResult.html","title":"MemberRulesResult - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"none - method","slug":"none-method","link":"#none-method","children":[]},{"level":2,"title":"count - method","slug":"count-method","link":"#count-method","children":[]},{"level":2,"title":"count - method","slug":"count-method-1","link":"#count-method-1","children":[]},{"level":2,"title":"count - method","slug":"count-method-2","link":"#count-method-2","children":[]}],"git":{"updatedTime":1674726569000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/classes/rules/result/MemberRulesResult.md"}');export{e as data}; diff --git a/assets/MemberRulesResult.html-4XM5SrCj.js b/assets/MemberRulesResult.html-4XM5SrCj.js new file mode 100644 index 0000000..0ef0f95 --- /dev/null +++ b/assets/MemberRulesResult.html-4XM5SrCj.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-503f5f8b","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/result/MemberRulesResult.html","title":"MemberRulesResult - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"none - method","slug":"none-method","link":"#none-method","children":[]},{"level":2,"title":"count - method","slug":"count-method","link":"#count-method","children":[]},{"level":2,"title":"count - method","slug":"count-method-1","link":"#count-method-1","children":[]},{"level":2,"title":"count - method","slug":"count-method-2","link":"#count-method-2","children":[]}],"git":{"updatedTime":1674666410000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/result/MemberRulesResult.md"}');export{e as data}; diff --git a/assets/MemberRulesResult.html-N7SQp4D9.js b/assets/MemberRulesResult.html-N7SQp4D9.js new file mode 100644 index 0000000..e66a5a6 --- /dev/null +++ b/assets/MemberRulesResult.html-N7SQp4D9.js @@ -0,0 +1,6 @@ +import{_ as s,o as e,c as o,a}from"./app-Un_zyw_U.js";const n={},l=a(`class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
+
变更记录
v1.0.0
添加
功能描述
当前
Member
查找条件结果实现类。
fun none(): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置当前
Member
在查找条件中个数为0
。
fun count(num: Int): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置当前
Member
在查找条件中需要全部匹配的个数。
fun count(numRange: IntRange): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置当前
Member
在查找条件中需要全部匹配的个数范围。
fun count(conditions: CountConditions): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
`,30),t=[l];function c(p,r){return e(),o("div",null,t)}const i=s(n,[["render",c],["__file","MemberRulesResult.html.vue"]]);export{i as default}; diff --git a/assets/MemberRulesResult.html-rcTdNW24.js b/assets/MemberRulesResult.html-rcTdNW24.js new file mode 100644 index 0000000..6b88891 --- /dev/null +++ b/assets/MemberRulesResult.html-rcTdNW24.js @@ -0,0 +1,6 @@ +import{_ as s,o as e,c as o,a as n}from"./app-Un_zyw_U.js";const a={},t=n(`设置当前
Member
在查找条件中需要全部匹配的个数条件。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
+
Change Records
v1.0.0
first
Function Illustrate
当前
Member
查找条件结果实现类。
fun none(): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Member
在查找条件中个数为0
。
fun count(num: Int): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Member
在查找条件中需要全部匹配的个数。
fun count(numRange: IntRange): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Member
在查找条件中需要全部匹配的个数范围。
fun count(conditions: CountConditions): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
`,31),l=[t];function c(r,p){return e(),o("div",null,l)}const i=s(a,[["render",c],["__file","MemberRulesResult.html.vue"]]);export{i as default}; diff --git a/assets/MethodFinder.html-9zE4fEos.js b/assets/MethodFinder.html-9zE4fEos.js new file mode 100644 index 0000000..7613b1f --- /dev/null +++ b/assets/MethodFinder.html-9zE4fEos.js @@ -0,0 +1,81 @@ +import{_ as s,o as a,c as n,a as o}from"./app-Un_zyw_U.js";const e={},l=o(`设置当前
Member
在查找条件中需要全部匹配的个数条件。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MethodFinder internal constructor(override val classSet: Class<*>) : MemberBaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
Method
查找类。
可通过指定类型查找指定 Method
或一组 Method
。
var name: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称。
Pay Attention
若不填写名称则必须存在一个其它条件。
var paramCount: Int
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
var returnType: Any?
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值,可不填写返回值。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
标识符筛选条件。
可不设置筛选条件。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun emptyParam(): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
空参数、无参数。
fun param(vararg paramType: Any): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Method
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。
Pay Attention
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun param(conditions: ObjectsConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数条件。
Pay Attention
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun order(): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
顺序筛选字节码的下标。
fun name(value: String): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称。
Pay Attention
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun name(conditions: NameConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称条件。
Pay Attention
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(num: Int): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数。
若参数个数小于零则忽略并使用 param
。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(numRange: IntRange): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun returnType(value: Any): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值。
可不填写返回值。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun returnType(conditions: ObjectConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值条件。
可不填写返回值。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
Change Records
v1.0.0
first
Function Illustrate
设置在
classSet
的所有父类中查找当前Method
。
Notice
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
Method
重查找实现类,可累计失败次数直到查找成功。
inline fun method(initiate: MethodConditions): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建需要重新查找的
Method
。
你可以添加多个备选 Method
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Method>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
修改
initiate
类型由 HashSet
修改为 MutableList
Function Illustrate
当在
RemedyPlan
中找到结果时。
Function Example
你可以方便地对重查找的 Method
实现 onFind
方法。
The following example
method {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
Change Records
v1.0.0
first
Function Illustrate
Method
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建监听结果事件方法体。
Function Example
你可以使用 lambda 形式创建 Result
类。
The following example
method {
+ // Your code here.
+}.result {
+ get(instance).call()
+ all(instance)
+ remedys {}
+ onNoSuchMethod {}
+}
+
fun get(instance: Any?): Instance
+
Change Records
v1.0.0
first
Function Illustrate
获得
Method
实例处理类。
若有多个 Method
结果只会返回第一个。
Pay Attention
若你设置了 remedys 请使用 wait 回调结果方法。
Function Example
你可以通过获得方法所在实例来执行 Method
。
The following example
method {
+ // Your code here.
+}.get(instance).call()
+
若当前为静态方法,你可以不设置实例。
The following example
method {
+ // Your code here.
+}.get().call()
+
fun all(instance: Any?): MutableList<Instance>
+
Change Records
v1.0.0
first
v1.0.3
修改
返回值类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Method
实例处理类数组。
返回全部查找条件匹配的多个 Method
实例结果。
Function Example
你可以通过此方法来获得当前条件结果中匹配的全部 Method
,其方法所在实例用法与 get
相同。
The following example
method {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Method?
+
Change Records
v1.0.0
first
Function Illustrate
得到
Method
本身。
若有多个 Method
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Method>
+
Change Records
v1.0.0
first
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Method
本身数组。
返回全部查找条件匹配的多个 Method
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
获得
Method
实例处理类,配合RemedyPlan
使用。
若有多个 Method
结果只会返回第一个。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(instance: Any?, initiate: MutableList<Instance>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
修改
initiate
类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Method
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Method
实例结果。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建
Method
重查找功能。
Function Example
当你遇到一种 Method
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchMethod
捕获异常二次查找 Method
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
The following example
method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
监听找不到
Method
时。
只会返回第一次的错误信息,不会返回 RemedyPlan
的错误信息。
fun ignored(): Result
+
Change Records
v1.0.0
first
Function Illustrate
忽略异常并停止打印任何错误日志。
Notice
此时若要监听异常结果,你需要手动实现 onNoSuchMethod 方法。
inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
+
Change Records
v1.0.0
first
Function Illustrate
Method
实例处理类。
fun call(vararg args: Any?): Any?
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,不指定返回值类型。
fun <T> invoke(vararg args: Any?): T?
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定T
返回值类型。
fun byte(vararg args: Any?): Byte?
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Byte 返回值类型。
fun int(vararg args: Any?): Int
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Int 返回值类型。
fun long(vararg args: Any?): Long
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Long 返回值类型。
fun short(vararg args: Any?): Short
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Short 返回值类型。
fun double(vararg args: Any?): Double
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Double 返回值类型。
fun float(vararg args: Any?): Float
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Float 返回值类型。
fun string(vararg args: Any?): String
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 String 返回值类型。
fun char(vararg args: Any?): Char
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Char 返回值类型。
fun boolean(vararg args: Any?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Boolean 返回值类型。
inline fun <reified T> array(vararg args: Any?): Array<T>
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Array 返回值类型。
inline fun <reified T> list(vararg args: Any?): List<T>
+
Change Records
v1.0.0
first
Function Illustrate
`,347),t=[l];function p(c,r){return a(),n("div",null,t)}const i=s(e,[["render",p],["__file","MethodFinder.html.vue"]]);export{i as default}; diff --git a/assets/MethodFinder.html-F3Nq1ta1.js b/assets/MethodFinder.html-F3Nq1ta1.js new file mode 100644 index 0000000..e352bcf --- /dev/null +++ b/assets/MethodFinder.html-F3Nq1ta1.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-155c9f97","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/members/MethodFinder.html","title":"MethodFinder - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"returnType - field","slug":"returntype-field","link":"#returntype-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"param - method","slug":"param-method-1","link":"#param-method-1","children":[]},{"level":2,"title":"order - method","slug":"order-method","link":"#order-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"name - method","slug":"name-method-1","link":"#name-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-2","link":"#paramcount-method-2","children":[]},{"level":2,"title":"returnType - method","slug":"returntype-method","link":"#returntype-method","children":[]},{"level":2,"title":"returnType - method","slug":"returntype-method-1","link":"#returntype-method-1","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchMethod - method","slug":"onnosuchmethod-method","link":"#onnosuchmethod-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]},{"level":3,"title":"array - method","slug":"array-method","link":"#array-method","children":[]},{"level":3,"title":"list - method","slug":"list-method","link":"#list-method","children":[]}]}],"git":{"updatedTime":1696172435000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/members/MethodFinder.md"}');export{e as data}; diff --git a/assets/MethodFinder.html-dHpCygp2.js b/assets/MethodFinder.html-dHpCygp2.js new file mode 100644 index 0000000..154681c --- /dev/null +++ b/assets/MethodFinder.html-dHpCygp2.js @@ -0,0 +1,81 @@ +import{_ as s,o as a,c as o,a as n}from"./app-Un_zyw_U.js";const e={},l=n(`执行
Method
,指定 List 返回值类型。
class MethodFinder internal constructor(override val classSet: Class<*>) : MemberBaseFinder
+
变更记录
v1.0.0
添加
功能描述
Method
查找类。
可通过指定类型查找指定 Method
或一组 Method
。
var name: String
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称。
特别注意
若不填写名称则必须存在一个其它条件。
var paramCount: Int
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
var returnType: Any?
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值,可不填写返回值。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
标识符筛选条件。
可不设置筛选条件。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun emptyParam(): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
空参数、无参数。
fun param(vararg paramType: Any): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Method
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。
特别注意
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun param(conditions: ObjectsConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数条件。
特别注意
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun order(): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
顺序筛选字节码的下标。
fun name(value: String): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称。
特别注意
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun name(conditions: NameConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称条件。
特别注意
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(num: Int): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数。
若参数个数小于零则忽略并使用 param
。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(numRange: IntRange): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun returnType(value: Any): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值。
可不填写返回值。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun returnType(conditions: ObjectConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值条件。
可不填写返回值。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
变更记录
v1.0.0
添加
功能描述
设置在
classSet
的所有父类中查找当前Method
。
注意
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
变更记录
v1.0.0
添加
功能描述
Method
重查找实现类,可累计失败次数直到查找成功。
inline fun method(initiate: MethodConditions): Result
+
变更记录
v1.0.0
添加
功能描述
创建需要重新查找的
Method
。
你可以添加多个备选 Method
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
变更记录
v1.0.0
添加
功能描述
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Method>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 HashSet
修改为 MutableList
功能描述
当在
RemedyPlan
中找到结果时。
功能示例
你可以方便地对重查找的 Method
实现 onFind
方法。
示例如下
method {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
变更记录
v1.0.0
添加
功能描述
Method
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建监听结果事件方法体。
功能示例
你可以使用 lambda 形式创建 Result
类。
示例如下
method {
+ // Your code here.
+}.result {
+ get(instance).call()
+ all(instance)
+ remedys {}
+ onNoSuchMethod {}
+}
+
fun get(instance: Any?): Instance
+
变更记录
v1.0.0
添加
功能描述
获得
Method
实例处理类。
若有多个 Method
结果只会返回第一个。
特别注意
若你设置了 remedys 请使用 wait 回调结果方法。
功能示例
你可以通过获得方法所在实例来执行 Method
。
示例如下
method {
+ // Your code here.
+}.get(instance).call()
+
若当前为静态方法,你可以不设置实例。
示例如下
method {
+ // Your code here.
+}.get().call()
+
fun all(instance: Any?): MutableList<Instance>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 ArrayList
修改为 MutableList
功能描述
获得
Method
实例处理类数组。
返回全部查找条件匹配的多个 Method
实例结果。
功能示例
你可以通过此方法来获得当前条件结果中匹配的全部 Method
,其方法所在实例用法与 get
相同。
示例如下
method {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Method?
+
变更记录
v1.0.0
添加
功能描述
得到
Method
本身。
若有多个 Method
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Method>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
功能描述
得到
Method
本身数组。
返回全部查找条件匹配的多个 Method
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
变更记录
v1.0.0
添加
功能描述
获得
Method
实例处理类,配合RemedyPlan
使用。
若有多个 Method
结果只会返回第一个。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(instance: Any?, initiate: MutableList<Instance>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 ArrayList
修改为 MutableList
功能描述
获得
Method
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Method
实例结果。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建
Method
重查找功能。
功能示例
当你遇到一种 Method
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchMethod
捕获异常二次查找 Method
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
示例如下
method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
监听找不到
Method
时。
只会返回第一次的错误信息,不会返回 RemedyPlan
的错误信息。
fun ignored(): Result
+
变更记录
v1.0.0
添加
功能描述
忽略异常并停止打印任何错误日志。
注意
此时若要监听异常结果,你需要手动实现 onNoSuchMethod 方法。
inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
+
变更记录
v1.0.0
添加
功能描述
Method
实例处理类。
fun call(vararg args: Any?): Any?
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,不指定返回值类型。
fun <T> invoke(vararg args: Any?): T?
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定T
返回值类型。
fun byte(vararg args: Any?): Byte?
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Byte 返回值类型。
fun int(vararg args: Any?): Int
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Int 返回值类型。
fun long(vararg args: Any?): Long
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Long 返回值类型。
fun short(vararg args: Any?): Short
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Short 返回值类型。
fun double(vararg args: Any?): Double
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Double 返回值类型。
fun float(vararg args: Any?): Float
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Float 返回值类型。
fun string(vararg args: Any?): String
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 String 返回值类型。
fun char(vararg args: Any?): Char
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Char 返回值类型。
fun boolean(vararg args: Any?): Boolean
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Boolean 返回值类型。
inline fun <reified T> array(vararg args: Any?): Array<T>
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Array 返回值类型。
inline fun <reified T> list(vararg args: Any?): List<T>
+
变更记录
v1.0.0
添加
功能描述
`,346),p=[l];function t(c,r){return a(),o("div",null,p)}const i=s(e,[["render",t],["__file","MethodFinder.html.vue"]]);export{i as default}; diff --git a/assets/MethodFinder.html-rrxJN8Pm.js b/assets/MethodFinder.html-rrxJN8Pm.js new file mode 100644 index 0000000..29a4ed1 --- /dev/null +++ b/assets/MethodFinder.html-rrxJN8Pm.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-012ee5a6","path":"/en/api/public/com/highcapable/yukireflection/finder/members/MethodFinder.html","title":"MethodFinder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"returnType - field","slug":"returntype-field","link":"#returntype-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"param - method","slug":"param-method-1","link":"#param-method-1","children":[]},{"level":2,"title":"order - method","slug":"order-method","link":"#order-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"name - method","slug":"name-method-1","link":"#name-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-2","link":"#paramcount-method-2","children":[]},{"level":2,"title":"returnType - method","slug":"returntype-method","link":"#returntype-method","children":[]},{"level":2,"title":"returnType - method","slug":"returntype-method-1","link":"#returntype-method-1","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchMethod - method","slug":"onnosuchmethod-method","link":"#onnosuchmethod-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]},{"level":3,"title":"array - method","slug":"array-method","link":"#array-method","children":[]},{"level":3,"title":"list - method","slug":"list-method","link":"#list-method","children":[]}]}],"git":{"updatedTime":1696172435000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":5}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/members/MethodFinder.md"}');export{e as data}; diff --git a/assets/MethodRules.html-0hkKQ1Lm.js b/assets/MethodRules.html-0hkKQ1Lm.js new file mode 100644 index 0000000..9910b68 --- /dev/null +++ b/assets/MethodRules.html-0hkKQ1Lm.js @@ -0,0 +1,13 @@ +import{_ as s,o as a,c as e,a as o}from"./app-Un_zyw_U.js";const n={},t=o(`执行
Method
,指定 List 返回值类型。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MethodRules internal constructor(private val rulesData: MethodRulesData) : BaseRules
+
Change Records
v1.0.0
first
Function Illustrate
Method
查找条件实现类。
var name: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称。
var paramCount: Int
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
var returnType: Any?
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值。
可不填写返回值。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
标识符筛选条件。
可不设置筛选条件。
fun emptyParam()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
空参数、无参数。
fun param(vararg paramType: Any)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Method
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。
Pay Attention
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
fun param(conditions: ObjectsConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数条件。
Pay Attention
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
fun name(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称条件。
fun paramCount(numRange: IntRange)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
fun paramCount(conditions: CountConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
fun returnType(conditions: ObjectConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值条件。
可不填写返回值。
`,84),p=[t];function c(l,r){return a(),e("div",null,p)}const i=s(n,[["render",c],["__file","MethodRules.html.vue"]]);export{i as default}; diff --git a/assets/MethodRules.html-SViWQxO9.js b/assets/MethodRules.html-SViWQxO9.js new file mode 100644 index 0000000..153990a --- /dev/null +++ b/assets/MethodRules.html-SViWQxO9.js @@ -0,0 +1,13 @@ +import{_ as s,o as a,c as o,a as e}from"./app-Un_zyw_U.js";const n={},p=e(`class MethodRules internal constructor(private val rulesData: MethodRulesData) : BaseRules
+
变更记录
v1.0.0
添加
功能描述
Method
查找条件实现类。
var name: String
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称。
var paramCount: Int
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
var returnType: Any?
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值。
可不填写返回值。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
标识符筛选条件。
可不设置筛选条件。
fun emptyParam()
+
变更记录
v1.0.0
添加
功能描述
设置
Method
空参数、无参数。
fun param(vararg paramType: Any)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Method
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。
特别注意
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
fun param(conditions: ObjectsConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数条件。
特别注意
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
fun name(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称条件。
fun paramCount(numRange: IntRange)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
fun paramCount(conditions: CountConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
fun returnType(conditions: ObjectConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值条件。
可不填写返回值。
`,83),t=[p];function c(l,d){return a(),o("div",null,t)}const i=s(n,[["render",c],["__file","MethodRules.html.vue"]]);export{i as default}; diff --git a/assets/MethodRules.html-aSRU9IHr.js b/assets/MethodRules.html-aSRU9IHr.js new file mode 100644 index 0000000..eacc210 --- /dev/null +++ b/assets/MethodRules.html-aSRU9IHr.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-2a3be6c9","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/MethodRules.html","title":"MethodRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"returnType - field","slug":"returntype-field","link":"#returntype-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"param - method","slug":"param-method-1","link":"#param-method-1","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"returnType - method","slug":"returntype-method","link":"#returntype-method","children":[]}],"git":{"updatedTime":1695808915000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/classes/rules/MethodRules.md"}');export{e as data}; diff --git a/assets/MethodRules.html-wOHbNM4H.js b/assets/MethodRules.html-wOHbNM4H.js new file mode 100644 index 0000000..e41e5e7 --- /dev/null +++ b/assets/MethodRules.html-wOHbNM4H.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5e7e121a","path":"/en/api/public/com/highcapable/yukireflection/finder/classes/rules/MethodRules.html","title":"MethodRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"returnType - field","slug":"returntype-field","link":"#returntype-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"param - method","slug":"param-method-1","link":"#param-method-1","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"returnType - method","slug":"returntype-method","link":"#returntype-method","children":[]}],"git":{"updatedTime":1695808915000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/classes/rules/MethodRules.md"}');export{e as data}; diff --git a/assets/ModifierRules.html-4vu7ZiXc.js b/assets/ModifierRules.html-4vu7ZiXc.js new file mode 100644 index 0000000..452a3fa --- /dev/null +++ b/assets/ModifierRules.html-4vu7ZiXc.js @@ -0,0 +1,14 @@ +import{_ as e,o as s,c as a,a as o}from"./app-Un_zyw_U.js";const n={},c=o(`class ModifierRules private constructor()
+
变更记录
v1.0.0
添加
功能描述
这是一个
Class
、Member
描述符条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
val isPublic: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含public
。
val isPrivate: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含private
。
val isProtected: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含protected
。
val isStatic: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含static
。
对于任意的静态 Class
、Member
可添加此描述进行确定。
注意
Kotlin → Jvm 后的 object 类中的方法并不是静态的。
val isFinal: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含final
。
注意
Kotlin → Jvm 后没有 open 符号标识的 Class、Member 和没有任何关联的 Class、Member 都将为 final。
val isSynchronized: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含synchronized
。
val isVolatile: Boolean
+
变更记录
v1.0.0
添加
功能描述
Field
类型是否包含volatile
。
val isTransient: Boolean
+
变更记录
v1.0.0
添加
功能描述
Field
类型是否包含transient
。
val isNative: Boolean
+
变更记录
v1.0.0
添加
功能描述
Method
类型是否包含native
。
对于任意 JNI 对接的 Method
可添加此描述进行确定。
val isInterface: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
类型是否包含interface
。
val isAbstract: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含abstract
。
对于任意的抽象 Class
、Member
可添加此描述进行确定。
val isStrict: Boolean
+
变更记录
v1.0.0
添加
功能描述
`,84),l=[c];function t(d,i){return s(),a("div",null,l)}const r=e(n,[["render",t],["__file","ModifierRules.html.vue"]]);export{r as default}; diff --git a/assets/ModifierRules.html-EHCxf6eb.js b/assets/ModifierRules.html-EHCxf6eb.js new file mode 100644 index 0000000..27d6994 --- /dev/null +++ b/assets/ModifierRules.html-EHCxf6eb.js @@ -0,0 +1,14 @@ +import{_ as e,o as s,c as a,a as o}from"./app-Un_zyw_U.js";const n={},t=o(`
Class
、Member
类型是否包含strictfp
。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ModifierRules private constructor()
+
Change Records
v1.0.0
first
Function Illustrate
这是一个
Class
、Member
描述符条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
val isPublic: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含public
。
val isPrivate: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含private
。
val isProtected: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含protected
。
val isStatic: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含static
。
对于任意的静态 Class
、Member
可添加此描述进行确定。
Notice
Kotlin → Jvm 后的 object 类中的方法并不是静态的。
val isFinal: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含final
。
Notice
Kotlin → Jvm 后没有 open 符号标识的 Class、Member 和没有任何关联的 Class、Member 都将为 final。
val isSynchronized: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含synchronized
。
val isVolatile: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Field
类型是否包含volatile
。
val isTransient: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Field
类型是否包含transient
。
val isNative: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Method
类型是否包含native
。
对于任意 JNI 对接的 Method
可添加此描述进行确定。
val isInterface: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
类型是否包含interface
。
val isAbstract: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含abstract
。
对于任意的抽象 Class
、Member
可添加此描述进行确定。
val isStrict: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
`,85),c=[t];function l(i,d){return s(),a("div",null,c)}const p=e(n,[["render",l],["__file","ModifierRules.html.vue"]]);export{p as default}; diff --git a/assets/ModifierRules.html-n9h96LhZ.js b/assets/ModifierRules.html-n9h96LhZ.js new file mode 100644 index 0000000..6944961 --- /dev/null +++ b/assets/ModifierRules.html-n9h96LhZ.js @@ -0,0 +1 @@ +const i=JSON.parse('{"key":"v-56071599","path":"/en/api/public/com/highcapable/yukireflection/finder/base/rules/ModifierRules.html","title":"ModifierRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"isPublic - i-ext-field","slug":"ispublic-i-ext-field","link":"#ispublic-i-ext-field","children":[]},{"level":2,"title":"isPrivate - i-ext-field","slug":"isprivate-i-ext-field","link":"#isprivate-i-ext-field","children":[]},{"level":2,"title":"isProtected - i-ext-field","slug":"isprotected-i-ext-field","link":"#isprotected-i-ext-field","children":[]},{"level":2,"title":"isStatic - i-ext-field","slug":"isstatic-i-ext-field","link":"#isstatic-i-ext-field","children":[]},{"level":2,"title":"isFinal - i-ext-field","slug":"isfinal-i-ext-field","link":"#isfinal-i-ext-field","children":[]},{"level":2,"title":"isSynchronized - i-ext-field","slug":"issynchronized-i-ext-field","link":"#issynchronized-i-ext-field","children":[]},{"level":2,"title":"isVolatile - i-ext-field","slug":"isvolatile-i-ext-field","link":"#isvolatile-i-ext-field","children":[]},{"level":2,"title":"isTransient - i-ext-field","slug":"istransient-i-ext-field","link":"#istransient-i-ext-field","children":[]},{"level":2,"title":"isNative - i-ext-field","slug":"isnative-i-ext-field","link":"#isnative-i-ext-field","children":[]},{"level":2,"title":"isInterface - i-ext-field","slug":"isinterface-i-ext-field","link":"#isinterface-i-ext-field","children":[]},{"level":2,"title":"isAbstract - i-ext-field","slug":"isabstract-i-ext-field","link":"#isabstract-i-ext-field","children":[]},{"level":2,"title":"isStrict - i-ext-field","slug":"isstrict-i-ext-field","link":"#isstrict-i-ext-field","children":[]}],"git":{"updatedTime":1674726569000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/base/rules/ModifierRules.md"}');export{i as data}; diff --git a/assets/ModifierRules.html-w8NPlak8.js b/assets/ModifierRules.html-w8NPlak8.js new file mode 100644 index 0000000..6b3d9a9 --- /dev/null +++ b/assets/ModifierRules.html-w8NPlak8.js @@ -0,0 +1 @@ +const i=JSON.parse('{"key":"v-701721ec","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/base/rules/ModifierRules.html","title":"ModifierRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"isPublic - i-ext-field","slug":"ispublic-i-ext-field","link":"#ispublic-i-ext-field","children":[]},{"level":2,"title":"isPrivate - i-ext-field","slug":"isprivate-i-ext-field","link":"#isprivate-i-ext-field","children":[]},{"level":2,"title":"isProtected - i-ext-field","slug":"isprotected-i-ext-field","link":"#isprotected-i-ext-field","children":[]},{"level":2,"title":"isStatic - i-ext-field","slug":"isstatic-i-ext-field","link":"#isstatic-i-ext-field","children":[]},{"level":2,"title":"isFinal - i-ext-field","slug":"isfinal-i-ext-field","link":"#isfinal-i-ext-field","children":[]},{"level":2,"title":"isSynchronized - i-ext-field","slug":"issynchronized-i-ext-field","link":"#issynchronized-i-ext-field","children":[]},{"level":2,"title":"isVolatile - i-ext-field","slug":"isvolatile-i-ext-field","link":"#isvolatile-i-ext-field","children":[]},{"level":2,"title":"isTransient - i-ext-field","slug":"istransient-i-ext-field","link":"#istransient-i-ext-field","children":[]},{"level":2,"title":"isNative - i-ext-field","slug":"isnative-i-ext-field","link":"#isnative-i-ext-field","children":[]},{"level":2,"title":"isInterface - i-ext-field","slug":"isinterface-i-ext-field","link":"#isinterface-i-ext-field","children":[]},{"level":2,"title":"isAbstract - i-ext-field","slug":"isabstract-i-ext-field","link":"#isabstract-i-ext-field","children":[]},{"level":2,"title":"isStrict - i-ext-field","slug":"isstrict-i-ext-field","link":"#isstrict-i-ext-field","children":[]}],"git":{"updatedTime":1674666410000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/base/rules/ModifierRules.md"}');export{i as data}; diff --git a/assets/NameRules.html-6iq8oL-B.js b/assets/NameRules.html-6iq8oL-B.js new file mode 100644 index 0000000..874fcd0 --- /dev/null +++ b/assets/NameRules.html-6iq8oL-B.js @@ -0,0 +1,9 @@ +import{_ as s,o as e,c as n,a}from"./app-Un_zyw_U.js";const o={},t=a(`
Class
、Member
类型是否包含strictfp
。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class NameRules private constructor()
+
Change Records
v1.0.0
first
Function Illustrate
这是一个模糊
Class
、Member
名称条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
fun String.isSynthetic(index: Int): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否为匿名类的主类调用对象。
fun String.isOnlySymbols(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有符号。
fun String.isOnlyLetters(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有字母。
fun String.isOnlyNumbers(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有数字。
fun String.isOnlyLettersNumbers(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有字母或数字。
fun String.isOnlyLowercase(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有小写字母。
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
fun String.isOnlyUppercase(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有大写字母。
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
`,52),l=[t];function r(p,c){return e(),n("div",null,l)}const d=s(o,[["render",r],["__file","NameRules.html.vue"]]);export{d as default}; diff --git a/assets/NameRules.html-9btOATID.js b/assets/NameRules.html-9btOATID.js new file mode 100644 index 0000000..70efcb9 --- /dev/null +++ b/assets/NameRules.html-9btOATID.js @@ -0,0 +1,9 @@ +import{_ as s,o as e,c as n,a}from"./app-Un_zyw_U.js";const o={},l=a(`class NameRules private constructor()
+
变更记录
v1.0.0
添加
功能描述
这是一个模糊
Class
、Member
名称条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
fun String.isSynthetic(index: Int): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否为匿名类的主类调用对象。
fun String.isOnlySymbols(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有符号。
fun String.isOnlyLetters(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有字母。
fun String.isOnlyNumbers(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有数字。
fun String.isOnlyLettersNumbers(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有字母或数字。
fun String.isOnlyLowercase(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有小写字母。
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
fun String.isOnlyUppercase(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有大写字母。
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
`,51),t=[l];function p(r,c){return e(),n("div",null,t)}const d=s(o,[["render",p],["__file","NameRules.html.vue"]]);export{d as default}; diff --git a/assets/NameRules.html-FTNuImB7.js b/assets/NameRules.html-FTNuImB7.js new file mode 100644 index 0000000..51070f4 --- /dev/null +++ b/assets/NameRules.html-FTNuImB7.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-264e7384","path":"/zh-cn/api/public/com/highcapable/yukireflection/finder/base/rules/NameRules.html","title":"NameRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"String.isSynthetic - i-ext-method","slug":"string-issynthetic-i-ext-method","link":"#string-issynthetic-i-ext-method","children":[]},{"level":2,"title":"String.isOnlySymbols - i-ext-method","slug":"string-isonlysymbols-i-ext-method","link":"#string-isonlysymbols-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyLetters - i-ext-method","slug":"string-isonlyletters-i-ext-method","link":"#string-isonlyletters-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyNumbers - i-ext-method","slug":"string-isonlynumbers-i-ext-method","link":"#string-isonlynumbers-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyLettersNumbers - i-ext-method","slug":"string-isonlylettersnumbers-i-ext-method","link":"#string-isonlylettersnumbers-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyLowercase - i-ext-method","slug":"string-isonlylowercase-i-ext-method","link":"#string-isonlylowercase-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyUppercase - i-ext-method","slug":"string-isonlyuppercase-i-ext-method","link":"#string-isonlyuppercase-i-ext-method","children":[]}],"git":{"updatedTime":1674666410000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/finder/base/rules/NameRules.md"}');export{e as data}; diff --git a/assets/NameRules.html-jW6PpEoY.js b/assets/NameRules.html-jW6PpEoY.js new file mode 100644 index 0000000..c837a19 --- /dev/null +++ b/assets/NameRules.html-jW6PpEoY.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-4ea9e766","path":"/en/api/public/com/highcapable/yukireflection/finder/base/rules/NameRules.html","title":"NameRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"String.isSynthetic - i-ext-method","slug":"string-issynthetic-i-ext-method","link":"#string-issynthetic-i-ext-method","children":[]},{"level":2,"title":"String.isOnlySymbols - i-ext-method","slug":"string-isonlysymbols-i-ext-method","link":"#string-isonlysymbols-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyLetters - i-ext-method","slug":"string-isonlyletters-i-ext-method","link":"#string-isonlyletters-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyNumbers - i-ext-method","slug":"string-isonlynumbers-i-ext-method","link":"#string-isonlynumbers-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyLettersNumbers - i-ext-method","slug":"string-isonlylettersnumbers-i-ext-method","link":"#string-isonlylettersnumbers-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyLowercase - i-ext-method","slug":"string-isonlylowercase-i-ext-method","link":"#string-isonlylowercase-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyUppercase - i-ext-method","slug":"string-isonlyuppercase-i-ext-method","link":"#string-isonlyuppercase-i-ext-method","children":[]}],"git":{"updatedTime":1674726569000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/finder/base/rules/NameRules.md"}');export{e as data}; diff --git a/assets/ObjectRules.html-EZNQwBuT.js b/assets/ObjectRules.html-EZNQwBuT.js new file mode 100644 index 0000000..e872b1e --- /dev/null +++ b/assets/ObjectRules.html-EZNQwBuT.js @@ -0,0 +1,2 @@ +import{_ as s,o as e,c as o,a}from"./app-Un_zyw_U.js";const n={},t=a(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ObjectRules private constructor(private val instance: Any)
+
Change Records
v1.0.0
first
Function Illustrate
这是一个任意对象条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
class ObjectRules private constructor(private val instance: Any)
+
变更记录
v1.0.0
添加
功能描述
这是一个任意对象条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
变更记录
v1.0.0
添加
功能描述
这是自定义
Member
和Class
相关功能的查找匹配以及invoke
的封装类。
open class LazyClass<T> internal constructor(
+ private val instance: Any,
+ private val initialize: Boolean,
+ private val loader: ClassLoaderInitializer?
+)
+
变更记录
v1.0.3
新增
功能描述
懒装载
Class
实例。
fun ClassLoader.listOfClasses(): List<String>
+
变更记录
v1.0.0
添加
功能描述
写出当前
ClassLoader
下所有Class
名称数组。
inline fun ClassLoader.searchClass(context: Context?, name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
变更记录
v1.0.0
添加
功能描述
通过当前
ClassLoader
按指定条件查找并得到 Dex 中的Class
。
特别注意
此方法在 Class 数量过多及查找条件复杂时会非常耗时。
建议启用 async 或设置 name 参数,name 参数将在当前 APP 不同版本中自动进行本地缓存以提升效率。
如果使用了 async 或 name 参数,则必须填写 context 参数。
此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
val Class<*>.hasExtends: Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否有继承关系,父类是Any
将被认为没有继承关系。
infix fun Class<*>?.extends(other: Class<*>?): Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否继承于other
。
如果当前 Class
就是 other
也会返回 true
。
如果当前 Class
为 null
或 other
为 null
会返回 false
。
功能示例
你可以使用此方法来判断两个 Class
是否存在继承关系。
示例如下
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否继承于 B
+if (classA extends classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.notExtends(other: Class<*>?): Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否不继承于other
。
此方法相当于 extends
的反向判断。
功能示例
你可以使用此方法来判断两个 Class
是否不存在继承关系。
示例如下
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否不继承于 B
+if (classA notExtends classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.implements(other: Class<*>?): Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否实现了other
接口类。
如果当前 Class
为 null
或 other
为 null
会返回 false
。
功能示例
你可以使用此方法来判断两个 Class
是否存在依赖关系。
示例如下
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否实现了 B 接口类
+if (classA implements classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.notImplements(other: Class<*>?): Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否未实现other
接口类。
此方法相当于 implements
的反向判断。
功能示例
你可以使用此方法来判断两个 Class
是否不存在依赖关系。
示例如下
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否未实现 B 接口类
+if (classA notImplements classB) {
+ // Your code here.
+}
+
fun Class<*>.toJavaPrimitiveType(): Class<*>
+
变更记录
v1.0.0
添加
功能描述
自动转换当前
Class
为 Java 原始类型 (Primitive Type)。
如果当前 Class
为 Java 或 Kotlin 基本类型将自动执行类型转换。
当前能够自动转换的基本类型如下。
kotlin.Unit
java.lang.Void
java.lang.Boolean
java.lang.Integer
java.lang.Float
java.lang.Double
java.lang.Long
java.lang.Short
java.lang.Character
java.lang.Byte
fun String.toClass(loader: ClassLoader?, initialize: Boolean): Class<*>
+
inline fun <reified T> String.toClass(loader: ClassLoader?, initialize: Boolean): Class<T>
+
变更记录
v1.0.0
添加
功能描述
通过字符串类名转换为
loader
中的实体类。
功能示例
你可以直接填写你要查找的目标 Class
,必须在默认 ClassLoader
下存在。
示例如下
"com.example.demo.DemoClass".toClass()
+
你还可以自定义 Class
所在的 ClassLoader
。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
你还可以指定 Class
的目标类型。
示例如下
// 指定的 DemoClass 必须存在或为可访问的 stub
+"com.example.demo.DemoClass".toClass<DemoClass>()
+
你还可以设置在获取到这个 Class
时是否自动执行其默认的静态方法块,默认情况下不会执行。
示例如下
// 获取并执行 DemoClass 默认的静态方法块
+"com.example.demo.DemoClass".toClass(initialize = true)
+
默认的静态方法块在 Java 中使用如下方式定义。
示例如下
public class DemoClass {
+
+ static {
+ // 这里是静态方法块的内容
+ }
+
+ public DemoClass() {
+ // ...
+ }
+}
+
fun String.toClassOrNull(loader: ClassLoader?, initialize: Boolean): Class<*>?
+
inline fun <reified T> String.toClassOrNull(loader: ClassLoader?, initialize: Boolean): Class<T>?
+
变更记录
v1.0.0
添加
功能描述
通过字符串类名转换为
loader
中的实体类。
找不到 Class
会返回 null
,不会抛出异常。
功能示例
用法请参考 String.toClass 方法。
inline fun <reified T> classOf(loader: ClassLoader?, initialize: Boolean): Class<T>
+
变更记录
v1.0.0
添加
功能描述
通过
T
得到其Class
实例并转换为实体类。
功能示例
我们要获取一个 Class
在 Kotlin 下不通过反射时应该这样做。
示例如下
DemoClass::class.java
+
现在,你可以直接 cast
一个实例并获取它的 Class
对象,必须在当前 ClassLoader
下存在。
示例如下
classOf<DemoClass>()
+
若目标存在的 Class
为 stub
,通过这种方式,你还可以自定义 Class
所在的 ClassLoader
。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+classOf<DemoClass>(customClassLoader)
+
fun lazyClass(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<Any>
+
inline fun <reified T> lazyClass(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<T>
+
fun lazyClass(variousClass: VariousClass, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<Any>
+
变更记录
v1.0.3
新增
功能描述
懒装载
Class
。
fun lazyClassOrNull(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<Any>
+
inline fun <reified T> lazyClassOrNull(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<T>
+
fun lazyClassOrNull(variousClass: VariousClass, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<Any>
+
变更记录
v1.0.3
新增
功能描述
懒装载
Class
。
fun String.hasClass(loader: ClassLoader?): Boolean
+
变更记录
v1.0.0
添加
功能描述
通过字符串类名使用指定的
ClassLoader
查找是否存在。
功能示例
你可以轻松的使用此方法判断字符串中的类是否存在,效果等同于直接使用 Class.forName
。
示例如下
if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
填入方法中的 loader
参数可判断指定的 ClassLoader
中的 Class
是否存在。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找变量是否存在。
inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找方法是否存在。
inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找构造方法是否存在。
inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找
Member
中匹配的描述符。
inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找
Class
中匹配的描述符。
inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
+
变更记录
v1.0.0
添加
功能描述
查找并得到变量。
inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
+
变更记录
v1.0.0
添加
功能描述
查找并得到方法。
inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
变更记录
v1.0.0
添加
功能描述
查找并得到构造方法。
fun Class<*>.generic(): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前
Class
的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前
Class
的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun <reified T : Any> T.current(ignored: Boolean): CurrentClass
+
inline fun <reified T : Any> T.current(ignored: Boolean, initiate: CurrentClass.() -> Unit): T
+
变更记录
v1.0.0
添加
功能描述
获得当前实例的类操作对象。
inline fun Class<*>.buildOf(vararg args: Any?, initiate: ConstructorConditions): Any?
+
inline fun <T> Class<*>.buildOf(vararg args: Any?, initiate: ConstructorConditions): T?
+
变更记录
v1.0.0
添加
功能描述
通过构造方法创建新实例,指定类型
T
或任意类型Any
。
inline fun Class<*>.allMethods(isAccessible: Boolean, result: (index: Int, method: Method) -> Unit)
+
变更记录
v1.0.0
添加
功能描述
遍历当前类中的所有方法。
inline fun Class<*>.allConstructors(isAccessible: Boolean, result: (index: Int, constructor: Constructor<*>) -> Unit)
+
变更记录
v1.0.0
添加
功能描述
遍历当前类中的所有构造方法。
inline fun Class<*>.allFields(isAccessible: Boolean, result: (index: Int, field: Field) -> Unit)
+
变更记录
v1.0.0
添加
功能描述
`,257),p=[e];function t(c,r){return a(),n("div",null,p)}const i=s(o,[["render",t],["__file","ReflectionFactory.html.vue"]]);export{i as default}; diff --git a/assets/ReflectionFactory.html-NQiaTVE5.js b/assets/ReflectionFactory.html-NQiaTVE5.js new file mode 100644 index 0000000..532b797 --- /dev/null +++ b/assets/ReflectionFactory.html-NQiaTVE5.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-728f231c","path":"/en/api/public/com/highcapable/yukireflection/factory/ReflectionFactory.html","title":"ReflectionFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"LazyClass - class","slug":"lazyclass-class","link":"#lazyclass-class","children":[]},{"level":2,"title":"ClassLoader.listOfClasses - ext-method","slug":"classloader-listofclasses-ext-method","link":"#classloader-listofclasses-ext-method","children":[]},{"level":2,"title":"ClassLoader.searchClass - ext-method","slug":"classloader-searchclass-ext-method","link":"#classloader-searchclass-ext-method","children":[]},{"level":2,"title":"Class.hasExtends - ext-field","slug":"class-hasextends-ext-field","link":"#class-hasextends-ext-field","children":[]},{"level":2,"title":"Class?.extends - ext-method","slug":"class-extends-ext-method","link":"#class-extends-ext-method","children":[]},{"level":2,"title":"Class?.notExtends - ext-method","slug":"class-notextends-ext-method","link":"#class-notextends-ext-method","children":[]},{"level":2,"title":"Class?.implements - ext-method","slug":"class-implements-ext-method","link":"#class-implements-ext-method","children":[]},{"level":2,"title":"Class?.notImplements - ext-method","slug":"class-notimplements-ext-method","link":"#class-notimplements-ext-method","children":[]},{"level":2,"title":"Class.toJavaPrimitiveType - ext-method","slug":"class-tojavaprimitivetype-ext-method","link":"#class-tojavaprimitivetype-ext-method","children":[]},{"level":2,"title":"String.toClass - ext-method","slug":"string-toclass-ext-method","link":"#string-toclass-ext-method","children":[]},{"level":2,"title":"String.toClassOrNull - ext-method","slug":"string-toclassornull-ext-method","link":"#string-toclassornull-ext-method","children":[]},{"level":2,"title":"classOf - method","slug":"classof-method","link":"#classof-method","children":[]},{"level":2,"title":"lazyClass - method","slug":"lazyclass-method","link":"#lazyclass-method","children":[]},{"level":2,"title":"lazyClassOrNull - method","slug":"lazyclassornull-method","link":"#lazyclassornull-method","children":[]},{"level":2,"title":"String.hasClass - ext-method","slug":"string-hasclass-ext-method","link":"#string-hasclass-ext-method","children":[]},{"level":2,"title":"Class.hasField - ext-method","slug":"class-hasfield-ext-method","link":"#class-hasfield-ext-method","children":[]},{"level":2,"title":"Class.hasMethod - ext-method","slug":"class-hasmethod-ext-method","link":"#class-hasmethod-ext-method","children":[]},{"level":2,"title":"Class.hasConstructor - ext-method","slug":"class-hasconstructor-ext-method","link":"#class-hasconstructor-ext-method","children":[]},{"level":2,"title":"Member.hasModifiers - ext-method","slug":"member-hasmodifiers-ext-method","link":"#member-hasmodifiers-ext-method","children":[]},{"level":2,"title":"Class.hasModifiers - ext-method","slug":"class-hasmodifiers-ext-method","link":"#class-hasmodifiers-ext-method","children":[]},{"level":2,"title":"Class.field - ext-method","slug":"class-field-ext-method","link":"#class-field-ext-method","children":[]},{"level":2,"title":"Class.method - ext-method","slug":"class-method-ext-method","link":"#class-method-ext-method","children":[]},{"level":2,"title":"Class.constructor - ext-method","slug":"class-constructor-ext-method","link":"#class-constructor-ext-method","children":[]},{"level":2,"title":"Class.generic - ext-method","slug":"class-generic-ext-method","link":"#class-generic-ext-method","children":[]},{"level":2,"title":"Class.generic - ext-method","slug":"class-generic-ext-method-1","link":"#class-generic-ext-method-1","children":[]},{"level":2,"title":"Any.current - ext-method","slug":"any-current-ext-method","link":"#any-current-ext-method","children":[]},{"level":2,"title":"Class.buildOf - ext-method","slug":"class-buildof-ext-method","link":"#class-buildof-ext-method","children":[]},{"level":2,"title":"Class.allMethods - ext-method","slug":"class-allmethods-ext-method","link":"#class-allmethods-ext-method","children":[]},{"level":2,"title":"Class.allConstructors - ext-method","slug":"class-allconstructors-ext-method","link":"#class-allconstructors-ext-method","children":[]},{"level":2,"title":"Class.allFields - ext-method","slug":"class-allfields-ext-method","link":"#class-allfields-ext-method","children":[]}],"git":{"updatedTime":1696530015000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/factory/ReflectionFactory.md"}');export{e as data}; diff --git a/assets/ReflectionFactory.html-e_EIy99E.js b/assets/ReflectionFactory.html-e_EIy99E.js new file mode 100644 index 0000000..d15e692 --- /dev/null +++ b/assets/ReflectionFactory.html-e_EIy99E.js @@ -0,0 +1,99 @@ +import{_ as s,o as a,c as n,a as l}from"./app-Un_zyw_U.js";const o={},e=l(`遍历当前类中的所有变量。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
这是自定义
Member
和Class
相关功能的查找匹配以及invoke
的封装类。
open class LazyClass<T> internal constructor(
+ private val instance: Any,
+ private val initialize: Boolean,
+ private val loader: ClassLoaderInitializer?
+)
+
Change Records
v1.2.0
added
Function Illustrate
懒装载
Class
实例。
fun ClassLoader.listOfClasses(): List<String>
+
Change Records
v1.0.0
first
Function Illustrate
写出当前
ClassLoader
下所有Class
名称数组。
inline fun ClassLoader.searchClass(context: Context?, name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
Change Records
v1.0.0
first
Function Illustrate
通过当前
ClassLoader
按指定条件查找并得到 Dex 中的Class
。
Pay Attention
此方法在 Class 数量过多及查找条件复杂时会非常耗时。
建议启用 async 或设置 name 参数,name 参数将在当前 APP 不同版本中自动进行本地缓存以提升效率。
如果使用了 async 或 name 参数,则必须填写 context 参数。
此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
val Class<*>.hasExtends: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否有继承关系,父类是Any
将被认为没有继承关系。
infix fun Class<*>?.extends(other: Class<*>?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否继承于other
。
如果当前 Class
就是 other
也会返回 true
。
如果当前 Class
为 null
或 other
为 null
会返回 false
。
Function Example
你可以使用此方法来判断两个 Class
是否存在继承关系。
The following example
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否继承于 B
+if (classA extends classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.notExtends(other: Class<*>?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否不继承于other
。
此方法相当于 extends
的反向判断。
Function Example
你可以使用此方法来判断两个 Class
是否不存在继承关系。
The following example
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否不继承于 B
+if (classA notExtends classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.implements(other: Class<*>?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否实现了other
接口类。
如果当前 Class
为 null
或 other
为 null
会返回 false
。
Function Example
你可以使用此方法来判断两个 Class
是否存在依赖关系。
The following example
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否实现了 B 接口类
+if (classA implements classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.notImplements(other: Class<*>?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否未实现other
接口类。
此方法相当于 implements
的反向判断。
Function Example
你可以使用此方法来判断两个 Class
是否不存在依赖关系。
The following example
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否未实现 B 接口类
+if (classA notImplements classB) {
+ // Your code here.
+}
+
fun Class<*>.toJavaPrimitiveType(): Class<*>
+
Change Records
v1.0.0
first
Function Illustrate
自动转换当前
Class
为 Java 原始类型 (Primitive Type)。
如果当前 Class
为 Java 或 Kotlin 基本类型将自动执行类型转换。
当前能够自动转换的基本类型如下。
kotlin.Unit
java.lang.Void
java.lang.Boolean
java.lang.Integer
java.lang.Float
java.lang.Double
java.lang.Long
java.lang.Short
java.lang.Character
java.lang.Byte
fun String.toClass(loader: ClassLoader?, initialize: Boolean): Class<*>
+
inline fun <reified T> String.toClass(loader: ClassLoader?, initialize: Boolean): Class<T>
+
Change Records
v1.0.0
first
Function Illustrate
通过字符串类名转换为
loader
中的实体类。
Function Example
你可以直接填写你要查找的目标 Class
,必须在默认 ClassLoader
下存在。
The following example
"com.example.demo.DemoClass".toClass()
+
你还可以自定义 Class
所在的 ClassLoader
。
The following example
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
你还可以指定 Class
的目标类型。
The following example
// 指定的 DemoClass 必须存在或为可访问的 stub
+"com.example.demo.DemoClass".toClass<DemoClass>()
+
你还可以设置在获取到这个 Class
时是否自动执行其默认的静态方法块,默认情况下不会执行。
The following example
// 获取并执行 DemoClass 默认的静态方法块
+"com.example.demo.DemoClass".toClass(initialize = true)
+
默认的静态方法块在 Java 中使用如下方式定义。
The following example
public class DemoClass {
+
+ static {
+ // 这里是静态方法块的内容
+ }
+
+ public DemoClass() {
+ // ...
+ }
+}
+
fun String.toClassOrNull(loader: ClassLoader?, initialize: Boolean): Class<*>?
+
inline fun <reified T> String.toClassOrNull(loader: ClassLoader?, initialize: Boolean): Class<T>?
+
Change Records
v1.0.0
first
Function Illustrate
通过字符串类名转换为
loader
中的实体类。
找不到 Class
会返回 null
,不会抛出异常。
Function Example
用法请参考 String.toClass 方法。
inline fun <reified T> classOf(loader: ClassLoader?, initialize: Boolean): Class<T>
+
Change Records
v1.0.0
first
Function Illustrate
通过
T
得到其Class
实例并转换为实体类。
Function Example
我们要获取一个 Class
在 Kotlin 下不通过反射时应该这样做。
The following example
DemoClass::class.java
+
现在,你可以直接 cast
一个实例并获取它的 Class
对象,必须在当前 ClassLoader
下存在。
The following example
classOf<DemoClass>()
+
若目标存在的 Class
为 stub
,通过这种方式,你还可以自定义 Class
所在的 ClassLoader
。
The following example
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+classOf<DemoClass>(customClassLoader)
+
fun lazyClass(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<Any>
+
inline fun <reified T> lazyClass(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<T>
+
fun lazyClass(variousClass: VariousClass, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<Any>
+
Change Records
v1.0.3
added
Function Illustrate
懒装载
Class
。
fun lazyClassOrNull(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<Any>
+
inline fun <reified T> lazyClassOrNull(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<T>
+
fun lazyClassOrNull(variousClass: VariousClass, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<Any>
+
Change Records
v1.0.3
added
Function Illustrate
懒装载
Class
。
fun String.hasClass(loader: ClassLoader?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
通过字符串类名使用指定的
ClassLoader
查找是否存在。
Function Example
你可以轻松的使用此方法判断字符串中的类是否存在,效果等同于直接使用 Class.forName
。
The following example
if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
填入方法中的 loader
参数可判断指定的 ClassLoader
中的 Class
是否存在。
The following example
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找变量是否存在。
inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找方法是否存在。
inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找构造方法是否存在。
inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找
Member
中匹配的描述符。
inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找
Class
中匹配的描述符。
inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
+
Change Records
v1.0.0
first
Function Illustrate
查找并得到变量。
inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
+
Change Records
v1.0.0
first
Function Illustrate
查找并得到方法。
inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
Change Records
v1.0.0
first
Function Illustrate
查找并得到构造方法。
fun Class<*>.generic(): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
Class
的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
Class
的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun <reified T : Any> T.current(ignored: Boolean): CurrentClass
+
inline fun <reified T : Any> T.current(ignored: Boolean, initiate: CurrentClass.() -> Unit): T
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例的类操作对象。
inline fun Class<*>.buildOf(vararg args: Any?, initiate: ConstructorConditions): Any?
+
inline fun <T> Class<*>.buildOf(vararg args: Any?, initiate: ConstructorConditions): T?
+
Change Records
v1.0.0
first
Function Illustrate
通过构造方法创建新实例,指定类型
T
或任意类型Any
。
inline fun Class<*>.allMethods(isAccessible: Boolean, result: (index: Int, method: Method) -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
遍历当前类中的所有方法。
inline fun Class<*>.allConstructors(isAccessible: Boolean, result: (index: Int, constructor: Constructor<*>) -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
遍历当前类中的所有构造方法。
inline fun Class<*>.allFields(isAccessible: Boolean, result: (index: Int, field: Field) -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
`,258),p=[e];function t(c,r){return a(),n("div",null,p)}const i=s(o,[["render",t],["__file","ReflectionFactory.html.vue"]]);export{i as default}; diff --git a/assets/ReflectionFactory.html-fNUb_WhR.js b/assets/ReflectionFactory.html-fNUb_WhR.js new file mode 100644 index 0000000..690e339 --- /dev/null +++ b/assets/ReflectionFactory.html-fNUb_WhR.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-b3841eba","path":"/zh-cn/api/public/com/highcapable/yukireflection/factory/ReflectionFactory.html","title":"ReflectionFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"LazyClass - class","slug":"lazyclass-class","link":"#lazyclass-class","children":[]},{"level":2,"title":"ClassLoader.listOfClasses - ext-method","slug":"classloader-listofclasses-ext-method","link":"#classloader-listofclasses-ext-method","children":[]},{"level":2,"title":"ClassLoader.searchClass - ext-method","slug":"classloader-searchclass-ext-method","link":"#classloader-searchclass-ext-method","children":[]},{"level":2,"title":"Class.hasExtends - ext-field","slug":"class-hasextends-ext-field","link":"#class-hasextends-ext-field","children":[]},{"level":2,"title":"Class?.extends - ext-method","slug":"class-extends-ext-method","link":"#class-extends-ext-method","children":[]},{"level":2,"title":"Class?.notExtends - ext-method","slug":"class-notextends-ext-method","link":"#class-notextends-ext-method","children":[]},{"level":2,"title":"Class?.implements - ext-method","slug":"class-implements-ext-method","link":"#class-implements-ext-method","children":[]},{"level":2,"title":"Class?.notImplements - ext-method","slug":"class-notimplements-ext-method","link":"#class-notimplements-ext-method","children":[]},{"level":2,"title":"Class.toJavaPrimitiveType - ext-method","slug":"class-tojavaprimitivetype-ext-method","link":"#class-tojavaprimitivetype-ext-method","children":[]},{"level":2,"title":"String.toClass - ext-method","slug":"string-toclass-ext-method","link":"#string-toclass-ext-method","children":[]},{"level":2,"title":"String.toClassOrNull - ext-method","slug":"string-toclassornull-ext-method","link":"#string-toclassornull-ext-method","children":[]},{"level":2,"title":"classOf - method","slug":"classof-method","link":"#classof-method","children":[]},{"level":2,"title":"lazyClass - method","slug":"lazyclass-method","link":"#lazyclass-method","children":[]},{"level":2,"title":"lazyClassOrNull - method","slug":"lazyclassornull-method","link":"#lazyclassornull-method","children":[]},{"level":2,"title":"String.hasClass - ext-method","slug":"string-hasclass-ext-method","link":"#string-hasclass-ext-method","children":[]},{"level":2,"title":"Class.hasField - ext-method","slug":"class-hasfield-ext-method","link":"#class-hasfield-ext-method","children":[]},{"level":2,"title":"Class.hasMethod - ext-method","slug":"class-hasmethod-ext-method","link":"#class-hasmethod-ext-method","children":[]},{"level":2,"title":"Class.hasConstructor - ext-method","slug":"class-hasconstructor-ext-method","link":"#class-hasconstructor-ext-method","children":[]},{"level":2,"title":"Member.hasModifiers - ext-method","slug":"member-hasmodifiers-ext-method","link":"#member-hasmodifiers-ext-method","children":[]},{"level":2,"title":"Class.hasModifiers - ext-method","slug":"class-hasmodifiers-ext-method","link":"#class-hasmodifiers-ext-method","children":[]},{"level":2,"title":"Class.field - ext-method","slug":"class-field-ext-method","link":"#class-field-ext-method","children":[]},{"level":2,"title":"Class.method - ext-method","slug":"class-method-ext-method","link":"#class-method-ext-method","children":[]},{"level":2,"title":"Class.constructor - ext-method","slug":"class-constructor-ext-method","link":"#class-constructor-ext-method","children":[]},{"level":2,"title":"Class.generic - ext-method","slug":"class-generic-ext-method","link":"#class-generic-ext-method","children":[]},{"level":2,"title":"Class.generic - ext-method","slug":"class-generic-ext-method-1","link":"#class-generic-ext-method-1","children":[]},{"level":2,"title":"Any.current - ext-method","slug":"any-current-ext-method","link":"#any-current-ext-method","children":[]},{"level":2,"title":"Class.buildOf - ext-method","slug":"class-buildof-ext-method","link":"#class-buildof-ext-method","children":[]},{"level":2,"title":"Class.allMethods - ext-method","slug":"class-allmethods-ext-method","link":"#class-allmethods-ext-method","children":[]},{"level":2,"title":"Class.allConstructors - ext-method","slug":"class-allconstructors-ext-method","link":"#class-allconstructors-ext-method","children":[]},{"level":2,"title":"Class.allFields - ext-method","slug":"class-allfields-ext-method","link":"#class-allfields-ext-method","children":[]}],"git":{"updatedTime":1696530015000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/factory/ReflectionFactory.md"}');export{e as data}; diff --git a/assets/VariableTypeFactory.html-L20wMFG_.js b/assets/VariableTypeFactory.html-L20wMFG_.js new file mode 100644 index 0000000..02cc525 --- /dev/null +++ b/assets/VariableTypeFactory.html-L20wMFG_.js @@ -0,0 +1 @@ +import{_ as o,r,o as n,c,b as t,d as e,e as s,a as i}from"./app-Un_zyw_U.js";const l={},p=i('遍历当前类中的所有变量。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
',6),d={href:"https://github.com/HighCapable/YukiReflection/blob/master/yukireflection/src/main/java/com/highcapable/yukireflection/type/java/VariableTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"};function h(u,b){const a=r("ExternalLinkIcon");return n(),c("div",null,[p,t("p",null,[e("详情可 "),t("a",d,[e("点击这里"),s(a)]),e(" 进行查看。")])])}const _=o(l,[["render",h],["__file","VariableTypeFactory.html.vue"]]);export{_ as default}; diff --git a/assets/VariableTypeFactory.html-aKba1Svi.js b/assets/VariableTypeFactory.html-aKba1Svi.js new file mode 100644 index 0000000..f64fdaf --- /dev/null +++ b/assets/VariableTypeFactory.html-aKba1Svi.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-12f074b0","path":"/en/api/public/com/highcapable/yukireflection/type/java/VariableTypeFactory.html","title":"VariableTypeFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[],"git":{"updatedTime":1696445455000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":5}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/type/java/VariableTypeFactory.md"}');export{a as data}; diff --git a/assets/VariableTypeFactory.html-vuqEkE15.js b/assets/VariableTypeFactory.html-vuqEkE15.js new file mode 100644 index 0000000..67a5643 --- /dev/null +++ b/assets/VariableTypeFactory.html-vuqEkE15.js @@ -0,0 +1 @@ +import{_ as o,r,o as c,c as n,b as a,d as e,e as s,a as l}from"./app-Un_zyw_U.js";const i={},p=l('这是一个预置反射类型的常量类,主要为 Java 相关基本变量类型的
Class
内容,跟随版本更新会逐一进行增加。
变更记录
v1.0.0
添加
功能描述
',5),d={href:"https://github.com/HighCapable/YukiReflection/blob/master/yukireflection/src/main/java/com/highcapable/yukireflection/type/java/VariableTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"};function _(b,h){const t=r("ExternalLinkIcon");return c(),n("div",null,[p,a("p",null,[e("详情可 "),a("a",d,[e("点击这里"),s(t)]),e(" 进行查看。")])])}const f=o(i,[["render",_],["__file","VariableTypeFactory.html.vue"]]);export{f as default}; diff --git a/assets/VariableTypeFactory.html-z7CY3MNH.js b/assets/VariableTypeFactory.html-z7CY3MNH.js new file mode 100644 index 0000000..7af2928 --- /dev/null +++ b/assets/VariableTypeFactory.html-z7CY3MNH.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-5ad1133e","path":"/zh-cn/api/public/com/highcapable/yukireflection/type/java/VariableTypeFactory.html","title":"VariableTypeFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[],"git":{"updatedTime":1696445455000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/type/java/VariableTypeFactory.md"}');export{a as data}; diff --git a/assets/VariousClass.html-27EKagHz.js b/assets/VariousClass.html-27EKagHz.js new file mode 100644 index 0000000..d6d2018 --- /dev/null +++ b/assets/VariousClass.html-27EKagHz.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-c234ac1e","path":"/zh-cn/api/public/com/highcapable/yukireflection/bean/VariousClass.html","title":"VariousClass - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":2,"title":"getOrNull - method","slug":"getornull-method","link":"#getornull-method","children":[]}],"git":{"updatedTime":1674666410000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/bean/VariousClass.md"}');export{e as data}; diff --git a/assets/VariousClass.html-N1_WPt67.js b/assets/VariousClass.html-N1_WPt67.js new file mode 100644 index 0000000..94932db --- /dev/null +++ b/assets/VariousClass.html-N1_WPt67.js @@ -0,0 +1,4 @@ +import{_ as s,o as a,c as o,a as e}from"./app-Un_zyw_U.js";const l={},n=e(`这是一个预置反射类型的常量类,主要为 Java 相关基本变量类型的
Class
内容,跟随版本更新会逐一进行增加。
class VariousClass(private vararg val name: String)
+
变更记录
v1.0.0
添加
功能描述
这是一个不确定性
Class
类名装载器,通过name
装载Class
名称数组。
fun get(loader: ClassLoader? = null, initialize: Boolean): Class<*>
+
变更记录
v1.0.0
添加
功能描述
获取匹配的实体类。
使用当前 loader
装载目标 Class
。
fun getOrNull(loader: ClassLoader? = null, initialize: Boolean): Class<*>?
+
变更记录
v1.0.0
添加
功能描述
获取匹配的实体类。
使用当前 loader
装载目标 Class
。
匹配不到 Class
会返回 null
,不会抛出异常。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class VariousClass(private vararg val name: String)
+
Change Records
v1.0.0
first
Function Illustrate
这是一个不确定性
Class
类名装载器,通过name
装载Class
名称数组。
fun get(loader: ClassLoader? = null, initialize: Boolean): Class<*>
+
Change Records
v1.0.0
first
Function Illustrate
获取匹配的实体类。
使用当前 loader
装载目标 Class
。
fun getOrNull(loader: ClassLoader? = null, initialize: Boolean): Class<*>?
+
Change Records
v1.0.0
first
Function Illustrate
获取匹配的实体类。
使用当前 loader
装载目标 Class
。
匹配不到 Class
会返回 null
,不会抛出异常。
变更记录
v1.0.0
添加
功能描述
',5),p={href:"https://github.com/HighCapable/YukiReflection/blob/master/yukireflection/src/main/java/com/highcapable/yukireflection/type/android/ViewTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"};function _(h,y){const t=c("ExternalLinkIcon");return r(),n("div",null,[l,o("p",null,[e("详情可 "),o("a",p,[e("点击这里"),s(t)]),e(" 进行查看。")])])}const k=a(d,[["render",_],["__file","ViewTypeFactory.html.vue"]]);export{k as default}; diff --git a/assets/ViewTypeFactory.html-BlJgDBiK.js b/assets/ViewTypeFactory.html-BlJgDBiK.js new file mode 100644 index 0000000..f69623e --- /dev/null +++ b/assets/ViewTypeFactory.html-BlJgDBiK.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-be0e3220","path":"/en/api/public/com/highcapable/yukireflection/type/android/ViewTypeFactory.html","title":"ViewTypeFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[],"git":{"updatedTime":1696445455000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/type/android/ViewTypeFactory.md"}');export{e as data}; diff --git a/assets/ViewTypeFactory.html-a4OWMkml.js b/assets/ViewTypeFactory.html-a4OWMkml.js new file mode 100644 index 0000000..1623374 --- /dev/null +++ b/assets/ViewTypeFactory.html-a4OWMkml.js @@ -0,0 +1 @@ +import{_ as a,r as n,o as r,c,b as t,d as e,e as s,a as i}from"./app-Un_zyw_U.js";const l={},p=i('这是一个预置反射类型的常量类,主要为
Android
相关Widget
的Class
内容,跟随版本更新会逐一进行增加。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
',6),d={href:"https://github.com/HighCapable/YukiReflection/blob/master/yukireflection/src/main/java/com/highcapable/yukireflection/type/android/ViewTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"};function h(u,f){const o=n("ExternalLinkIcon");return r(),c("div",null,[p,t("p",null,[e("详情可 "),t("a",d,[e("点击这里"),s(o)]),e(" 进行查看。")])])}const m=a(l,[["render",h],["__file","ViewTypeFactory.html.vue"]]);export{m as default}; diff --git a/assets/ViewTypeFactory.html-tP76iwqq.js b/assets/ViewTypeFactory.html-tP76iwqq.js new file mode 100644 index 0000000..724d52c --- /dev/null +++ b/assets/ViewTypeFactory.html-tP76iwqq.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-12826b1f","path":"/zh-cn/api/public/com/highcapable/yukireflection/type/android/ViewTypeFactory.html","title":"ViewTypeFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[],"git":{"updatedTime":1696445455000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/type/android/ViewTypeFactory.md"}');export{e as data}; diff --git a/assets/YLog.html-BiSru-dl.js b/assets/YLog.html-BiSru-dl.js new file mode 100644 index 0000000..55e0e34 --- /dev/null +++ b/assets/YLog.html-BiSru-dl.js @@ -0,0 +1,5 @@ +import{_ as e,o as s,c as o,a}from"./app-Un_zyw_U.js";const n={},t=a(`这是一个预置反射类型的常量类,主要为
Android
相关Widget
的Class
内容,跟随版本更新会逐一进行增加。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
object YLog
+
Change Records
v1.0.3
added
Function Illustrate
全局 Log 管理类。
object Configs
+
Change Records
v1.0.3
added
Function Illustrate
配置
YLog
。
var tag: String
+
Change Records
v1.0.3
added
Function Illustrate
这是一个调试日志的全局标识。
默认文案为 YukiReflection
。
你可以修改为你自己的文案。
var isEnable: Boolean
+
Change Records
v1.0.3
added
Function Illustrate
是否启用调试日志的输出功能。
关闭后将会停用 YukiReflection
对全部日志的输出。
当 isEnable
关闭后 YukiReflection.Configs.isDebug
也将同时关闭。
object YLog
+
变更记录
v1.0.3
新增
功能描述
全局 Log 管理类。
object Configs
+
变更记录
v1.0.3
新增
功能描述
配置
YLog
。
var tag: String
+
变更记录
v1.0.3
新增
功能描述
这是一个调试日志的全局标识。
默认文案为 YukiReflection
。
你可以修改为你自己的文案。
var isEnable: Boolean
+
变更记录
v1.0.3
新增
功能描述
是否启用调试日志的输出功能。
关闭后将会停用 YukiReflection
对全部日志的输出。
当 isEnable
关闭后 YukiReflection.Configs.isDebug
也将同时关闭。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
object YukiReflection
+
Change Records
v1.0.0
first
Function Illustrate
这是
YukiReflection
的装载调用类。
const val TAG: String
+
Change Records
v1.0.3
added
Function Illustrate
获取当前
YukiReflection
的名称 (标签)。
const val VERSION: String
+
Change Records
v1.0.3
added
Function Illustrate
获取当前
YukiReflection
的版本。
Change Records
v1.0.0
first
v1.0.3
deprecated
不再区分版本名称和版本号,请迁移到 VERSION
Change Records
v1.0.0
first
v1.0.3
deprecated
不再区分版本名称和版本号,请迁移到 VERSION
object Configs
+
Change Records
v1.0.0
first
Function Illustrate
对 API 相关功能的配置类。
inline fun debugLog(initiate: YLog.Configs.() -> Unit)
+
Change Records
v1.0.3
added
Function Illustrate
配置
YLog.Configs
相关参数。
Change Records
v1.0.0
first
v1.0.3
deprecated
请迁移到 debugLog
var isDebug: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否启用 Debug 模式。
默认不启用,启用后将交由日志输出管理器打印详细日志 (例如反射查找功能的耗时) 到控制台。
Change Records
v1.0.0
first
v1.0.3
deprecated
请迁移到 debugLog
Change Records
v1.0.0
first
v1.0.2
deprecated
Member
的直接缓存功能已被移除,因为其存在内存溢出 (OOM) 问题
inline fun configs(initiate: Configs.() -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
对
Configs
类实现了一个 lambda 方法体。
你可以轻松地调用它进行配置。
`,70),t=[c];function d(p,l){return o(),s("div",null,t)}const i=e(n,[["render",d],["__file","YukiReflection.html.vue"]]);export{i as default}; diff --git a/assets/YukiReflection.html-N0eAU_3r.js b/assets/YukiReflection.html-N0eAU_3r.js new file mode 100644 index 0000000..a706ceb --- /dev/null +++ b/assets/YukiReflection.html-N0eAU_3r.js @@ -0,0 +1,8 @@ +import{_ as e,o,c as s,a}from"./app-Un_zyw_U.js";const n={},c=a(`object YukiReflection
+
变更记录
v1.0.0
添加
功能描述
这是
YukiReflection
的装载调用类。
const val TAG: String
+
变更记录
v1.0.3
新增
功能描述
获取当前
YukiReflection
的名称 (标签)。
const val VERSION: String
+
变更记录
v1.0.3
新增
功能描述
获取当前
YukiReflection
的版本。
变更记录
v1.0.0
添加
v1.0.3
作废
不再区分版本名称和版本号,请迁移到 VERSION
变更记录
v1.0.0
添加
v1.0.3
作废
不再区分版本名称和版本号,请迁移到 VERSION
object Configs
+
变更记录
v1.0.0
添加
功能描述
对 API 相关功能的配置类。
inline fun debugLog(initiate: YLog.Configs.() -> Unit)
+
变更记录
v1.0.3
新增
功能描述
配置
YLog.Configs
相关参数。
变更记录
v1.0.0
添加
v1.0.3
作废
请迁移到 debugLog
var isDebug: Boolean
+
变更记录
v1.0.0
添加
功能描述
是否启用 Debug 模式。
默认不启用,启用后将交由日志输出管理器打印详细日志 (例如反射查找功能的耗时) 到控制台。
变更记录
v1.0.0
添加
v1.0.3
作废
请迁移到 debugLog
变更记录
v1.0.0
添加
v1.0.2
作废
Member
的直接缓存功能已被移除,因为其存在内存溢出 (OOM) 问题
inline fun configs(initiate: Configs.() -> Unit)
+
变更记录
v1.0.0
添加
功能描述
对
Configs
类实现了一个 lambda 方法体。
你可以轻松地调用它进行配置。
`,69),p=[c];function d(l,t){return o(),s("div",null,p)}const i=e(n,[["render",d],["__file","YukiReflection.html.vue"]]);export{i as default}; diff --git a/assets/YukiReflection.html-d5WSFYcp.js b/assets/YukiReflection.html-d5WSFYcp.js new file mode 100644 index 0000000..9f8ac34 --- /dev/null +++ b/assets/YukiReflection.html-d5WSFYcp.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-c088ede0","path":"/zh-cn/api/public/com/highcapable/yukireflection/YukiReflection.html","title":"YukiReflection - object","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"TAG - field","slug":"tag-field","link":"#tag-field","children":[]},{"level":2,"title":"VERSION - field","slug":"version-field","link":"#version-field","children":[]},{"level":2,"title":"Configs - object","slug":"configs-object","link":"#configs-object","children":[{"level":3,"title":"debugLog - method","slug":"debuglog-method","link":"#debuglog-method","children":[]},{"level":3,"title":"isDebug - field","slug":"isdebug-field","link":"#isdebug-field","children":[]}]},{"level":2,"title":"configs - method","slug":"configs-method","link":"#configs-method","children":[]}],"git":{"updatedTime":1695822096000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":7}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukireflection/YukiReflection.md"}');export{e as data}; diff --git a/assets/YukiReflection.html-wyZOo9RJ.js b/assets/YukiReflection.html-wyZOo9RJ.js new file mode 100644 index 0000000..6a87be7 --- /dev/null +++ b/assets/YukiReflection.html-wyZOo9RJ.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-23f4d2be","path":"/en/api/public/com/highcapable/yukireflection/YukiReflection.html","title":"YukiReflection - object","lang":"en-US","frontmatter":{"pageClass":"code-page"},"headers":[{"level":2,"title":"TAG - field","slug":"tag-field","link":"#tag-field","children":[]},{"level":2,"title":"VERSION - field","slug":"version-field","link":"#version-field","children":[]},{"level":2,"title":"Configs - object","slug":"configs-object","link":"#configs-object","children":[{"level":3,"title":"debugLog - method","slug":"debuglog-method","link":"#debuglog-method","children":[]},{"level":3,"title":"isDebug - field","slug":"isdebug-field","link":"#isdebug-field","children":[]}]},{"level":2,"title":"configs - method","slug":"configs-method","link":"#configs-method","children":[]}],"git":{"updatedTime":1695822096000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":8}]},"filePathRelative":"en/api/public/com/highcapable/yukireflection/YukiReflection.md"}');export{e as data}; diff --git a/assets/about.html--vPvG7gm.js b/assets/about.html--vPvG7gm.js new file mode 100644 index 0000000..824340f --- /dev/null +++ b/assets/about.html--vPvG7gm.js @@ -0,0 +1,16 @@ +import{_ as o,r as c,o as l,c as t,b as a,d as e,e as n,a as p}from"./app-Un_zyw_U.js";const r={},i=a("h1",{id:"关于此文档",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#关于此文档","aria-hidden":"true"},"#"),e(" 关于此文档")],-1),d={href:"https://v2.vuepress.vuejs.org/zh",target:"_blank",rel:"noopener noreferrer"},h=a("h2",{id:"许可证",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#许可证","aria-hidden":"true"},"#"),e(" 许可证")],-1),b={href:"https://github.com/HighCapable/YukiReflection/blob/master/LICENSE",target:"_blank",rel:"noopener noreferrer"},u=p(`Apache License Version 2.0
+
+Copyright (C) 2019 HighCapable
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
版权所有 © 2019 HighCapable
`,2);function _(y,f){const s=c("ExternalLinkIcon");return l(),t("div",null,[i,a("blockquote",null,[a("p",null,[e("此文档由 "),a("a",d,[e("VuePress"),n(s)]),e(" 强力驱动。")])]),h,a("p",null,[a("a",b,[e("Apache-2.0"),n(s)])]),u])}const m=o(r,[["render",_],["__file","about.html.vue"]]);export{m as default}; diff --git a/assets/about.html-a0D_ZdrJ.js b/assets/about.html-a0D_ZdrJ.js new file mode 100644 index 0000000..889ec0f --- /dev/null +++ b/assets/about.html-a0D_ZdrJ.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-41967128","path":"/zh-cn/about/about.html","title":"关于此文档","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"许可证","slug":"许可证","link":"#许可证","children":[]}],"git":{"updatedTime":1738723045000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":5}]},"filePathRelative":"zh-cn/about/about.md"}');export{t as data}; diff --git a/assets/about.html-esShpFQo.js b/assets/about.html-esShpFQo.js new file mode 100644 index 0000000..f585c96 --- /dev/null +++ b/assets/about.html-esShpFQo.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-7a15fe3b","path":"/en/about/about.html","title":"About This Document","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"License","slug":"license","link":"#license","children":[]}],"git":{"updatedTime":1738723045000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":5}]},"filePathRelative":"en/about/about.md"}');export{e as data}; diff --git a/assets/about.html-nADqWWz2.js b/assets/about.html-nADqWWz2.js new file mode 100644 index 0000000..864c603 --- /dev/null +++ b/assets/about.html-nADqWWz2.js @@ -0,0 +1,16 @@ +import{_ as o,r as t,o as c,c as l,b as e,d as a,e as n,a as p}from"./app-Un_zyw_U.js";const i={},r=e("h1",{id:"about-this-document",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#about-this-document","aria-hidden":"true"},"#"),a(" About This Document")],-1),d={href:"https://v2.vuepress.vuejs.org/en",target:"_blank",rel:"noopener noreferrer"},h=e("h2",{id:"license",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#license","aria-hidden":"true"},"#"),a(" License")],-1),b={href:"https://github.com/HighCapable/YukiReflection/blob/master/LICENSE",target:"_blank",rel:"noopener noreferrer"},u=p(`Apache License Version 2.0
+
+Copyright (C) 2019 HighCapable
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
Copyright © 2019 HighCapable
`,2);function _(y,m){const s=t("ExternalLinkIcon");return c(),l("div",null,[r,e("blockquote",null,[e("p",null,[a("This document is powered by "),e("a",d,[a("VuePress"),n(s)]),a(".")])]),h,e("p",null,[e("a",b,[a("Apache-2.0"),n(s)])]),u])}const f=o(i,[["render",_],["__file","about.html.vue"]]);export{f as default}; diff --git a/assets/api-example.html-4yu62_kW.js b/assets/api-example.html-4yu62_kW.js new file mode 100644 index 0000000..5e81cd2 --- /dev/null +++ b/assets/api-example.html-4yu62_kW.js @@ -0,0 +1,34 @@ +import{_ as s,o as n,c as a,a as e}from"./app-Un_zyw_U.js";const l={},i=e(`这里介绍了
YukiReflection
的基本配置方法。
YukiReflection
无需一些复杂的配置即可直接开始使用,且不会与 Java 原生的反射 API 冲突。
你可以在使用之前对 YukiReflection
进行一些功能配置。
你可以通过如下方式获取当前 YukiReflection
的标签和版本。
示例如下
// 获取标签
+val tag = YukiReflection.TAG
+// 获取版本
+val version = YukiReflection.VERSION
+
你可以通过获取版本进行一些不同版本差异的判断或用于显示在关于信息中。
小提示
更多功能请参考 YukiReflection。
你可以通过 YukiReflection.configs { ... }
方法或 YukiReflection.Configs
来配置相关功能。
你可以使用如下方式来自定义调试日志的标签。
API 内部的日志将会使用此标签进行打印。
示例如下
// 通过 configs 方法
+YukiReflection.configs {
+ debugLog {
+ tag = "YourCustomTag"
+ }
+}
+// 直接设置
+YLog.Configs.tag = "YourCustomTag"
+
你可以使用如下方式来启用或禁用 Debug 模式。
Debug 模式默认是关闭的,启用后将会打印详细日志 (例如反射查找功能的耗时) 到控制台。
示例如下
// 通过 configs 方法
+YukiReflection.configs {
+ isDebug = true
+}
+// 直接设置
+YukiReflection.Configs.isDebug = true
+
你可以使用如下方式来启用或禁用调试日志的输出功能。
此功能默认启用,关闭后将会停用 YukiReflection
对全部日志的输出。
示例如下
// 通过 configs 方法
+YukiReflection.configs {
+ debugLog {
+ isEnable = true
+ }
+}
+// 直接设置
+YLog.Configs.isEnable = true
+
为了一次性配置多个功能,你可以直接使用 YukiReflection.configs { ... }
方法进行配置。
示例如下
YukiReflection.configs {
+ debugLog {
+ tag = "YourCustomTag"
+ isEnable = true
+ }
+ isDebug = true
+}
+
小提示
更多功能请参考 YukiReflection.configs 方法、YukiReflection.Configs。
The basic configuration method of
YukiReflection
is introduced here.
YukiReflection
can be used directly without some complex configuration, and does not conflict with Java's native Reflection API.
You can configure some functions of YukiReflection
before using it.
You can get the current tag and version of YukiReflection
as follows.
The following example
// Get the tag
+val tag = YukiReflection.TAG
+// Get the version
+val version = YukiReflection.VERSION
+
You can judge the difference between different versions or display it in the about information by obtaining the version.
Tips
For more functions, please refer to YukiReflection.
You can configure related functions through YukiReflection.configs { ... }
method or YukiReflection.Configs
.
You can use the following methods to customize the tag of the debug log.
Logs inside the API will be printed using this tag.
The following example
// Via the configs method
+YukiReflection.configs {
+ debugLog {
+ tag = "YourCustomTag"
+ }
+}
+// Set directly
+YLog.Configs.tag = "YourCustomTag"
+
You can use the following methods to enable or disable Debug mode.
The Debug mode is disabled by default, and when enabled, detailed logs (such as the time spent on the reflective search function) will be printed to the console.
The following example
// Via the configs method
+YukiReflection.configs {
+ isDebug = true
+}
+// Set directly
+YukiReflection.Configs.isDebug = true
+
You can use the following methods to enable or disable debug logs.
This function is enabled by default, and disable will stop YukiReflection
output all logs.
The following example
// Via the configs method
+YukiReflection.configs {
+ debugLog {
+ isEnable = true
+ }
+}
+// Set directly
+YLog.Configs.isEnable = true
+
In order to configure multiple features at once, you can directly use the YukiReflection.configs { ... }
method to configure.
The following example
YukiReflection.configs {
+ debugLog {
+ tag = "YourCustomTag"
+ isEnable = true
+ }
+ isDebug = true
+}
+
Tips
For more functions, please refer to YukiReflection.configs method, YukiReflection.Configs.
异常是在开发过程经常遇到的主要问题,这里介绍了
YukiReflection
在使用过程中可能遇到的常见异常以及处理方式。
这里的异常说明只会同步最新的 API 版本,较旧的 API 版本的异常将不会再进行说明,请始终保持 API 版本为最新。
这些异常不会导致 APP 停止运行 (FC),但是会在控制台打印
E
级别的日志,也可能会停止继续执行相关功能。
loggerE
Method/Constructor/Field match type "TYPE" not allowed
异常原因
在查找方法、构造方法以及变量时设置了不允许的参数类型。
示例如下
// 查找一个方法
+method {
+ // 设置了无效的类型举例
+ param(false, 1, 0)
+ // 设置了无效的类型举例
+ returnType = false
+}
+
+// 查找一个变量
+field {
+ // 设置了无效的类型举例
+ type = false
+}
+
解决方案
在查找中 param
、returnType
、type
中仅接受 Class
、String
、VariousClass
类型的传值,不可传入参数实例。
示例如下
// 查找一个方法
+method {
+ // ✅ 正确的使用方法举例
+ param(BooleanType, IntType, IntType)
+ // ✅ 正确的使用方法举例
+ returnType = BooleanType
+ // ✅ 以下方案也是正确的
+ returnType = "java.lang.Boolean"
+}
+
+// 查找一个变量
+field {
+ // ✅ 正确的使用方法举例
+ type = BooleanType
+}
+
loggerE
NoSuchMethod/NoSuchConstructor/NoSuchField happend in [NAME]
异常原因
在查找方法、构造方法以及变量时并未找到目标方法、构造方法以及变量。
解决方案
请确认你的查找条件是否能正确匹配到目标 Class
中的指定方法、构造方法以及变量。
loggerE
Trying COUNT times and all failure by RemedyPlan
异常原因
使用 RemedyPlan
重新查找方法、构造方法、变量时依然没有找到方法、构造方法、变量。
解决方案
请确认你设置的 RemedyPlan
参数以及当前 APP 内存在的 Class
,再试一次。
loggerE
Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiReflection#ReflectionTool
异常原因
通过 ClassLoader.searchClass
找不到需要查找的 Class
对象。
示例如下
customClassLoader?.searchClass {
+ from(...)
+ // ...
+}.get()
+
解决方案
这是一个安全异常,请检查你设置的条件,使用相关工具查看所在 Dex 中的 Class
以及字节码对象特征,并再试一次。
loggerE
Can't find this Method/Constructor/Field in [CLASS]: CONTENT Generated by YukiReflection#ReflectionTool
异常原因
通过指定条件找不到需要查找的方法、构造方法以及变量。
示例如下
TargetClass.method {
+ name = "test"
+ param(BooleanType)
+}
+
解决方案
这是一个安全异常,请检查你设置的条件,使用相关工具查看所在 Class
中的字节码对象特征,并再试一次。
loggerE
The number of VagueType must be at least less than the count of paramTypes
异常原因
在 Method
、Constructor
查找条件中错误地使用了 VagueType
。
示例如下
TargetClass.method {
+ name = "test"
+ // <情景1>
+ param(VagueType)
+ // <情景2>
+ param(VagueType, VagueType ...)
+}
+
解决方案
VagueType
不能在方法、构造方法参数中完全填充,若存在这样的需求请使用 paramCount
。
loggerE
Field match type class is not found
异常原因
在查找变量时所设置的查找条件中 type
的 Class
实例未被找到。
示例如下
field {
+ name = "test"
+ // 假设这里设置的 type 的 Class 并不存在
+ type = "com.example.TestClass"
+}
+
解决方案
请检查查找条件中 type
的 Class
是否存在,然后再试一次。
loggerE
Method match returnType class is not found
异常原因
在查找方法时所设置的查找条件中 returnType
的 Class
实例未被找到。
示例如下
method {
+ name = "test"
+ // 假设这里设置的 returnType 的 Class 并不存在
+ returnType = "com.example.TestClass"
+}
+
解决方案
请检查查找条件中 returnType
的 Class
是否存在,然后再试一次。
loggerE
Method/Constructor match paramType[INDEX] class is not found
异常原因
在查找方法、构造方法时所设置的查找条件中 param
的 index
号下标的 Class
实例未被找到。
method {
+ name = "test"
+ // 假设这里设置的 1 号下标的 Class 并不存在
+ param(StringClass, "com.example.TestClass", BooleanType)
+}
+
解决方案
请检查查找条件中 param
的 index
号下标的 Class
是否存在,然后再试一次。
这些异常会直接导致 APP 停止运行 (FC),同时会在控制台打印
E
级别的日志。
NoClassDefFoundError
Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiReflection#ReflectionTool
异常原因
通过 String.toClass(...)
或 classOf<...>()
找不到需要查找的 Class
对象。
示例如下
"com.demo.Test".toClass()
+
解决方案
请检查当前字符串或实体匹配到的 Class
是否存在于当前 ClassLoader
,并再试一次。
IllegalStateException
ClassLoader [CLASSLOADER] is not a DexClassLoader
异常原因
使用 ClassLoader.searchClass
查找 Class
但是当前 ClassLoader
并不继承于 BaseDexClassLoader
。
解决方案
这种情况基本不存在,除非当前 APP 引用了非 ART 平台的可执行文件 (但是这种情况还是不会存在) 或当前 ClassLoader
为空。
IllegalStateException
VariousClass match failed of those CLASSES
异常原因
在使用 VariousClass
创建不确定的 Class
对象时全部的 Class
都没有被找到。
解决方案
检查当前 APP 内是否存在其中能够匹配的 Class
后,再试一次。
IllegalStateException
paramTypes is empty, please use emptyParam() instead
异常原因
在查找方法、构造方法时保留了空的 param
方法。
示例如下
method {
+ name = "test"
+ // 括号内没有填写任何参数
+ param()
+}
+
解决方案
若要标识此方法、构造方法没有参数,你可以有如下设置方法。
第一种,设置 emptyParam
(推荐)
示例如下
method {
+ name = "test"
+ emptyParam()
+}
+
第二种,设置 paramCount = 0
示例如下
method {
+ name = "test"
+ paramCount = 0
+}
+
IllegalStateException
Cannot create classes cache for "android", please remove "name" param
异常原因
在系统框架 (android) 中使用了 DexClassFinder
的缓存功能 searchClass(name = ...)
。
示例如下
searchClass(name = "test") {
+ from(...)
+ // ...
+}.get()
+
解决方案
由于缓存会将找到的 Class
名称存入 SharedPreferences
,但是系统框架不存在 data 目录,所以请不要在系统框架中使用此功能。
IllegalStateException
Target Class type cannot cast to TYPE
异常原因
使用 Class.toClass
、Class.toClassOrNull
、GenericClass.argument
方法将字符串类名转换为目标 Class
时声明了错误的类型。
以下使用 Class.toClass
方法来进行示例。
示例如下
// 假设目标类型是 Activity 但是被错误地转换为了 WrongClass 类型
+val clazz = "android.app.Activity".toClass<WrongClass>()
+
解决方案
示例如下
// <解决方案 1> 填写正确的类型
+val clazz1 = "android.app.Activity".toClass<Activity>()
+// <解决方案 2> 不填写泛型声明
+val clazz2 = "android.app.Activity".toClass()
+
请确保执行方法后声明的泛型是指定的目标 Class
类型,在不确定目标类型的情况下你可以不需要填写泛型声明。
Exceptions are the main problems often encountered in the development process. Here are some common exceptions that may be encountered during the use of
YukiReflection
and how to deal with them.
The exception description here will only synchronize the latest API version, and the exception of the older API version will not be described again, please always keep the API version up-to-date.
These exceptions will not cause the app to stop running (FC), but will print
E
level logs on the console, and may also stop continuing to execute related functions.
loggerE
Method/Constructor/Field match type "TYPE" not allowed
Abnormal
A disallowed parameter type was set when looking up methods, constructors, and variables.
The following example
// Find a method
+method {
+ // Invalid type example is set
+ param(false, 1, 0)
+ // Invalid type example is set
+ returnType = false
+}
+
+// Find a variable
+field {
+ // Invalid type example is set
+ type = false
+}
+
Solution
In the search, param
, returnType
, type
only accept Class
, String
, VariousClass
types, and parameter instances cannot be passed in.
The following example
// Find a method
+method {
+ // ✅ Examples of correct usage
+ param(BooleanType, IntType, IntType)
+ // ✅ Examples of correct usage
+ returnType = BooleanType
+ // ✅ The following scheme is also correct
+ returnType = "java.lang.Boolean"
+}
+
+// Find a variable
+field {
+ // ✅ Examples of correct usage
+ type = BooleanType
+}
+
loggerE
NoSuchMethod/NoSuchConstructor/NoSuchField happend in [NAME]
Abnormal
The target method, constructor, and variable were not found when looking for methods, constructors, and variables.
Solution
Please confirm that your search criteria can correctly match the specified methods, constructors and variables in the target Class
.
loggerE
Trying COUNT times and all failure by RemedyPlan
Abnormal
When using RemedyPlan
to search for methods, constructors, and variables, the methods, constructors, and variables are still not found.
Solution
Please confirm the RemedyPlan
parameter you set and the Class
that exists in the current app, and try again.
loggerE
Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiReflection#ReflectionTool
Abnormal
The Class
object to be searched for was not found via ClassLoader.searchClass
.
The following example
customClassLoader?.searchClass {
+ from(...)
+ // ...
+}.get()
+
Solution
This is a security exception, please check the conditions you set, use the relevant tools to view the Class
and bytecode object characteristics in the Dex and try again.
loggerE
Can't find this Method/Constructor/Field in [CLASS]: CONTENT Generated by YukiReflection#ReflectionTool
Abnormal
The methods, constructors, and variables that need to be found cannot be found by specifying conditions.
The following example
TargetClass.method {
+ name = "test"
+ param(BooleanType)
+}
+
Solution
This is a security exception, please check the conditions you set, use the relevant tools to view the bytecode object characteristics in the Class
, and try again.
loggerE
The number of VagueType must be at least less than the count of paramTypes
Abnormal
Incorrect use of VagueType
in Method
, Constructor
lookup conditions.
The following example
TargetClass.method {
+ name = "test"
+ // <Scenario 1>
+ param(VagueType)
+ // <Scenario 2>
+ param(VagueType, VagueType ...)
+}
+
Solution
VagueType
cannot be completely filled in method and constructor parameters. If there is such a requirement, please use paramCount
.
loggerE
Field match type class is not found
Abnormal
An instance of Class
for type
was not found in the lookup criteria set when looking up the variable.
The following example
field {
+ name = "test"
+ // Assume that the Class of the type set here does not exist
+ type = "com.example.TestClass"
+}
+
Solution
Please check if Class
of type
in the lookup condition exists and try again.
loggerE
Method match returnType class is not found
Abnormal
An instance of Class
of returnType
was not found in the search criteria set when looking up the method.
The following example
method {
+ name = "test"
+ // Assume that the Class of returnType set here does not exist
+ returnType = "com.example.TestClass"
+}
+
Solution
Please check if Class
of returnType
in the lookup condition exists and try again.
loggerE
Method/Constructor match paramType[INDEX] class is not found
Abnormal
The Class
instance subscripted by the index
number of param
was not found in the search conditions set when searching for methods and constructors.
method {
+ name = "test"
+ // Assume that the Class with subscript "No.1" set here does not exist
+ param(StringClass, "com.example.TestClass", BooleanType)
+}
+
Solution
Please check if the Class
subscripted by the index
number of param
in the lookup condition exists and try again.
These exceptions will directly cause the app to stop running (FC), at the same time print
E
level logs on the console.
NoClassDefFoundError
Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiReflection#ReflectionTool
Abnormal
The Class
object you were looking for was not found via String.toClass(...)
or classOf<...>()
.
The following example
"com.demo.Test".toClass()
+
Solution
Please check if the Class
matched by the current string or entity exists in the current ClassLoader
and try again.
IllegalStateException
ClassLoader [CLASSLOADER] is not a DexClassLoader
Abnormal
Use ClassLoader.searchClass
to find Class
but currently ClassLoader
does not extends BaseDexClassLoader
.
Solution
This situation basically does not exist, unless the current app references a Non-ART platform executable (which not realistic) or the current ClassLoader
is null.
IllegalStateException
VariousClass match failed of those CLASSES
Abnormal
All Class
were not found when creating indeterminate Class
objects using VariousClass
.
Solution
After checking whether there is a matching Class
in the current app and try again.
IllegalStateException
paramTypes is empty, please use emptyParam() instead
Abnormal
The empty param
method is preserved when looking up methods, constructors.
The following example
method {
+ name = "test"
+ // No parameters are filled in parentheses
+ param()
+}
+
Solution
To identify this method, the constructor has no parameters, you can have a setter method as follows.
The first way, set emptyParam
(recommended)
The following example
method {
+ name = "test"
+ emptyParam()
+}
+
The second way, set paramCount = 0
The following example
method {
+ name = "test"
+ paramCount = 0
+}
+
IllegalStateException
Cannot create classes cache for "android", please remove "name" param
Abnormal
The DexClassFinder
cache function searchClass(name = ...)
is used in the System Framework ("android") app.
The following example
searchClass(name = "test") {
+ from(...)
+ // ...
+}.get()
+
Solution
Since the cache will store the found Class
name in SharedPreferences
, but the data directory does not exist in the System Framework, so please do not use this function in the System Framework.
IllegalStateException
Target Class type cannot cast to TYPE
Abnormal
Wrong type declared when converting string class name to target Class
using Class.toClass
, Class.toClassOrNull
, GenericClass.argument
methods.
The following uses the Class.toClass
method as an example.
The following example
// Assume the target type is Activity but it was wrongly cast to WrongClass type
+val clazz = "android.app.Activity".toClass<WrongClass>()
+
Solution
The following example
// <Solution 1> Fill in the correct type
+val clazz1 = "android.app.Activity".toClass<Activity>()
+// <Solution 2> Do not fill in the generic declaration
+val clazz2 = "android.app.Activity".toClass()
+
Please ensure that the generic type declared after executing the method is the specified target Class
type, and you do not need to fill in the generic declaration if the target type is not sure.
The version update history of
YukiReflection
is recorded here.
Pay Attention
We will only maintain the latest API version, if you are using an outdate API version, you voluntarily renounce any possibility of maintenance.
Notice
To avoid translation time consumption, Changelog will use Google Translation from Chinese to English, please refer to the original text for actual reference.
Time zone of version release date: UTC+8
isAllowPrintingLogs
debugLog
methodYukiReflection.TAG
YukiReflection.API_VERSION_NAME
YukiReflection.API_VERSION_CODE
YukiReflection.VERSION
remendy
functionality in find methods, which now prints exceptions in stepsHashSet
to MutableList
method()
, constructor()
, field()
to directly obtain all object functions in the classconstructor()
no longer behaves like constructor { emptyParam() }
lazyClass
and lazyClassOrNull
methods to lazily load Class
isAllowPrintingLogs
debugLog
方法YukiReflection.TAG
YukiReflection.API_VERSION_NAME
YukiReflection.API_VERSION_CODE
YukiReflection.VERSION
remendy
功能,现在可以对其进行分步打印异常HashSet
改为 MutableList
method()
、constructor()
、field()
可直接获取到类中的所有对象功能constructor()
的行为不再是 constructor { emptyParam() }
lazyClass
、lazyClassOrNull
方法,可延迟装载 Class
Member
的直接缓存功能并作废 YukiReflection.Configs.isEnableMemberCache
Class
的缓存功能Sequence
,优化 Member
的查找速度与性能This page contains usage examples for all core features of
YukiReflection
.
Here are the extension functions related to the Class object itself.
Suppose we want to get a Class
that cannot be called directly.
Normally, we can use the standard reflection API to find this Class
.
The following example
// Class in the default ClassLoader environment
+var instance = Class.forName("com.demo.Test")
+// Specify the Class in the ClassLoader environment
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = customClassLoader?.loadClass("com.demo.Test")
+
This is probably not very friendly, and YukiReflection
provides you with a syntactic sugar that can be used anywhere.
The above writing can be written as YukiReflection
as follows.
The following example
// Get this Class directly
+var instance = "com.demo.Test".toClass()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = "com.demo.Test".toClass(customClassLoader)
+
If the current Class
does not exist, using the above method will throw an exception.
If you are not sure whether the Class
exists, you can refer to the following solutions.
The following example
// Get this Class directly
+// If not available, the result will be null but no exception will be thrown
+var instance = "com.demo.Test".toClassOrNull()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+// If not available, the result will be null but no exception will be thrown
+var instance = "com.demo.Test".toClassOrNull(customClassLoader)
+
We can also get an existing Class
object by mapping.
The following example
// Assume this Class can be obtained directly
+var instance = classOf<Test>()
+// We can also customize the ClassLoader where the Class is located, which is very effective for stubs
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = classOf<Test>(customClassLoader)
+
Tips
For more functions, please refer to classOf, String.toClass, String.toClassOrNull methods.
Suppose we want to get a Class
that cannot be called directly, but we do not need this Class
immediately.
At this time, you can use lazyClass
to complete this function.
The following example
// Lazy loading of this Class
+val instance by lazyClass("com.demo.Test")
+// Customize the ClassLoader where the Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+val instance by lazyClass("com.demo.Test") { customClassLoader }
+// Call this Class at the appropriate time
+instance.method {
+ // ...
+}
+
If the current Class
does not exist, using the above method will throw an exception.
If you are not sure whether Class
exists, you can refer to the following solution.
The following example
// Lazy loading of this Class
+// If not available, the result will be null but no exception will be thrown
+val instance by lazyClassOrNull("com.demo.Test")
+// Customize the ClassLoader where the Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+// If not available, the result will be null but no exception will be thrown
+val instance by lazyClassOrNull("com.demo.Test") { customClassLoader }
+// Call this Class at the appropriate time
+instance?.method {
+ // ...
+}
+
Tips
For more functions, please refer to lazyClass, lazyClassOrNull methods.
Suppose we want to determine whether a Class
exists.
Usually, we can use the standard reflection API to find this Class
to determine whether it exists by exception.
The following example
// Class in the default ClassLoader environment
+var isExist = try {
+ Class.forName("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+// Specify the Class in the ClassLoader environment
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var isExist = try {
+ customClassLoader?.loadClass("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+
This is probably not very friendly, and YukiReflection
provides you with a syntactic sugar that can be used anywhere.
The above writing can be written as YukiReflection
as follows.
The following example
// Check if this class exists
+var isExist = "com.demo.Test".hasClass()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var isExist = "com.demo.Test".hasClass(customClassLoader)
+
Tips
For more functions, please refer to String.hasClass method.
The Class
name in the current app's Dex after being obfuscated by tools such as R8 will be difficult to distinguish.
Its correct position is uncertain, and cannot be obtained directly through Object Conversion.
At this point, there is DexClassFinder
, its role is to determine the instance of this Class
by the bytecode features in the Class
that need to be searched.
Notice
This feature is only available on the Android platform.
At present, the function of DexClassFinder is still in the experimental stage.
Since the search function is only implemented through the Java layer, the performance may not reach the optimal level when there are too many current app's Class.
If something got wrong welcome to feedback.
Since it is a reflection-level API, currently it can only locate the specified Class through the characteristics of Class and Member, and cannot locate it by specifying the string and method content characteristics in the bytecode.
The speed of searching Class depends on the performance of the current device.
At present, the mainstream mobile processors are in the 3~10s range when the conditions are not complicated in the 10~15w number of Class, the fastest speed can reach within 25s under slightly complex conditions.
Please note that the more the same type Class is matched, the slower the speed.
Below is a simple usage example.
Suppose the following Class
is what we want, the names are obfuscated and may be different in each version.
The following example
package com.demo;
+
+public class a extends Activity implements Serializable {
+
+ public a(String var1) {
+ // ...
+ }
+
+ private String a;
+
+ private String b;
+
+ private boolean a;
+
+ protected void onCreate(Bundle var1) {
+ // ...
+ }
+
+ private static void a(String var1) {
+ // ...
+ }
+
+ private String a(boolean var1, String var2) {
+ // ...
+ }
+
+ private void a() {
+ // ...
+ }
+
+ public void a(boolean var1, a var2, b var3, String var4) {
+ // ...
+ }
+}
+
At this point, we want to get this Class
, you can use the ClassLoader.searchClass
method directly.
Each of the conditions demonstrated below is optional, and the more complex the conditions, the more accurate the positioning and the worse the performance.
The following example
searchClass {
+ // Start the search from the specified package name range
+ // In actual use, you can specify multiple package name ranges at the same time
+ from("com.demo")
+ // Specify the result of getSimpleName of the current Class
+ // You can directly make logical judgments on this string
+ // Here we are not sure whether its name is a, we can only judge the length of the string
+ simpleName { it.length == 1 }
+ // Specify the inherited parent class object
+ // If it is an existing stub, it can be directly represented by generics
+ extends<Activity>()
+ // Specify the inherited parent class object
+ // Which can be written directly as the full class name
+ // And you can also specify multiple objects at the same time
+ extends("android.app.Activity")
+ // Specify the implemented interface
+ // If it exists stub, can be directly represented by generics
+ implements<Serializable>()
+ // Specify the implemented interface
+ // Which can be written directly as a full class name, or you can specify multiple at the same time
+ implements("java.io.Serializable")
+ // Specify the type and style of the constructor
+ // And the number count that exists in the current class
+ constructor { param(StringClass) }.count(num = 1)
+ // Specify the type and style of the variable
+ // And the number that exists in the current class count
+ field { type = StringClass }.count(num = 2)
+ // Specify the type and style of the variable
+ // And the number that exists in the current class count
+ field { type = BooleanType }.count(num = 1)
+ // Directly specify the number of all variables that exist in the current class count
+ field().count(num = 3)
+ // If you think the number of variables is indeterminate
+ // You can also use the following custom conditions
+ field().count(1..3)
+ field().count { it >= 3 }
+ // Specify the type and style of the method
+ // And the number that exists in the current class count
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // Specify the modifier, and the number count in the current class
+ method {
+ modifiers { isStatic && isPrivate }
+ param(StringClass)
+ returnType = UnitType
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // Specify the modifier, and the number count in the current class
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, StringClass)
+ returnType = StringClass
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // Specify the modifier, and the number count in the current class
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ emptyParam()
+ returnType = UnitType
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // As well as the modifier and VagueType
+ // And the number count that exists in the current class
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, VagueType, VagueType, StringClass)
+ returnType = UnitType
+ }.count(num = 1)
+ // Directly specify the number of all methods that exist in the current class count
+ method().count(num = 5)
+ // If you think the number of methods is uncertain, you can also use the following custom conditions
+ method().count(1..5)
+ method().count { it >= 5 }
+ // Directly specify the number of all members existing in the current class count
+ // Members include: Field, Method, Constructor
+ member().count(num = 9)
+ // There must be a static modifier in all members, you can add this condition like this
+ member {
+ modifiers { isStatic }
+ }
+}.get() // Get the instance of this Class itself, if not found, it will return null
+
Tips
The conditional usage of Field, Method, Constructor in the above usage is consistent with the related usage in Member Extensions, with only minor differences.
For more functions, please refer to MemberRules, FieldRules, MethodRules, ConstructorRules.
By default, DexClassFinder
will use synchronous mode to search Class
, which will block the current thread until it finds or finds an exception.
If the search takes too long, it may cause ANR problems to the current app.
In response to the above problems, we can enable asynchronous, just add the parameter async = true
, which will not require you to start a thread again, the API has already handled the related problems for you.
Notice
To use this function, you need to pass in the Context of the current app as the first method parameter.
For the asynchronous case you need to use the wait method to get the result, the get method will no longer work.
The following example
val context: Context // Assume this is the Context of the current app
+searchClass(context, async = true) {
+ // ...
+}.wait { class1 ->
+ // Get asynchronous result
+}
+searchClass(context, async = true) {
+ // ...
+}.wait { class2 ->
+ // Get asynchronous result
+}
+
In this way, our search process runs asynchronously, it will not block the main thread, and each search will be performed in a separate thread at the same time, which can achieve the effect of parallel tasks.
Since the search is performed again every time the current app is reopened, this is a waste of repetitive performance when the current app's version is unchanged.
At this point, we can locally cache the search results of the current app's version by specifying the name
parameter.
Next time, the found class name will be directly read from the local cache.
The local cache uses SharedPreferences
, which will be saved to the app's data directory and will be re-cached after the app's version is updated.
After enabling the local cache, async = true
will be set at the same time, you don't need to set it manually.
Notice
To use this function, you need to pass in the Context of the current app as the first method parameter.
The following example
val context: Context // Assume this is the Context of the current app
+searchClass(context, name = "com.demo.class1") {
+ // ...
+}.wait { class1 ->
+ // Get asynchronous result
+}
+searchClass(context, name = "com.demo.class2") {
+ // ...
+}.wait { class2 ->
+ // Get asynchronous result
+}
+
If you want to clear the local cache manually, you can use the following method to clear the current version of the current app's cache.
The following example
val context: Context // Assume this is the Context of the current app
+DexClassFinder.clearCache(context)
+
You can also clear the app's cache for a specific version.
The following example
val context: Context // Assume this is the Context of the current app
+DexClassFinder.clearCache(context, versionName = "1.0", versionCode = 1)
+
If you need to search a set of Class
at the same time using a fixed condition, then you only need to use the all
or waitAll
method to get the result.
// Synchronous search, use all to get all the results found by the conditions
+searchClass {
+ // ...
+}.all().forEach { clazz ->
+ // Get each result
+}
+// Synchronous search, using all { ... } to iterate over each result
+searchClass {
+ // ...
+}.all { clazz ->
+ // Get each result
+}
+// Asynchronous search, use waitAll to get all the results found by the conditions
+val context: Context // Assume this is the Context of the current app
+searchClass(context, async = true) {
+ // ...
+}.waitAll { classes ->
+ classes.forEach {
+ // Get each result
+ }
+}
+
Tips
For more functions, please refer to ClassLoader.searchClass method.
Here are the extension functions related to the Class bytecode member variables Field, Method, Constructor.
Tips
Member is the interface description object of Field, Method, Constructor, which is the general term for the bytecode members in Class in Java reflection.
Suppose there is such a Class
.
The following example
package com.demo;
+
+public class BaseTest {
+
+ public BaseTest() {
+ // ...
+ }
+
+ public BaseTest(boolean isInit) {
+ // ...
+ }
+
+ private void doBaseTask(String taskName) {
+ // ...
+ }
+}
+
package com.demo;
+
+public class Test extends BaseTest {
+
+ public Test() {
+ // ...
+ }
+
+ public Test(boolean isInit) {
+ // ...
+ }
+
+ private static TAG = "Test";
+
+ private BaseTest baseInstance;
+
+ private String a;
+
+ private boolean a;
+
+ private boolean isTaskRunning = false;
+
+ private static void init() {
+ // ...
+ }
+
+ private void doTask(String taskName) {
+ // ...
+ }
+
+ private void release(String taskName, Function<boolean, String> task, boolean isFinish) {
+ // ...
+ }
+
+ private void stop() {
+ // ...
+ }
+
+ private String getName() {
+ // ...
+ }
+
+ private void b() {
+ // ...
+ }
+
+ private void b(String a) {
+ // ...
+ }
+}
+
Suppose we want to get the doTask
method of Test
and execute it.
Normally, we can use the standard reflection API to find this method.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using reflection API
+Test::class.java
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(instance, "task_name")
+
This is probably not very friendly, and YukiReflection
provides you with a syntactic sugar that can be used anywhere.
The above writing can be written as YukiReflection
as follows.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doTask"
+ param(StringClass)
+}.get(instance).call("task_name")
+
Tips
For more features, please refer to MethodFinder.
Similarly, we need to get the isTaskRunning
field can also be written as follows.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.field {
+ name = "isTaskRunning"
+ type = BooleanType
+}.get(instance).any() // Any instantiates an object of any type of Field
+
Tips
For more features, please refer to FieldFinder.
Maybe you also want to get the current Class
constructor, the same can be achieved.
The following example
Test::class.java.constructor {
+ param(BooleanType)
+}.get().call(true) // Can create a new instance
+
If you want to get the no-argument constructor of Class
, you can write it as follows.
The following example
Test::class.java.constructor().get().call() // Create a new instance
+
Tips
For more features, please refer to ConstructorFinder.
Suppose we want to get the getName
method in Class
, which can be implemented as follows.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+ returnType = StringClass
+}.get(instance).string() // Get the result of the method
+
Through observation, it is found that there is only one method named getName
in this Class
, so can we make it simpler?
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+}.get(instance).string() // Get the result of the method
+
Yes, you can refine your find criteria for methods that do not change exactly.
When using only get
or wait
methods to get results, YukiReflection
will match the first found result in bytecode order by default.
The problem comes again, this Class
has a release
method, but its method parameters are very long, and some types may not be directly available.
Normally we would use param(...)
to find this method, but is there an easier way.
At this point, after determining the uniqueness of the method, you can use paramCount
to find the method.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "release"
+ // At this point
+ // We don't have to determine the specific type of method parameters, just write the number
+ paramCount = 3
+}.get(instance) // Get this method
+
Although the above example can be successfully matched, it is not accurate.
At this time, you can also use VagueType
to fill in the method parameter type that you do not want to fill in.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "release"
+ // Use VagueType to fill in the type you don't want to fill in
+ // While ensuring that other types can match
+ param(StringClass, VagueType, BooleanType)
+}.get(instance) // Get this method
+
If you are not sure about the type of each parameter, you can create a conditional method body with the param { ... }
method.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "release"
+ // Get the it (Class) method parameter type array instance
+ // To only determine the known type and its position
+ param { it[0] == StringClass && it[2] == BooleanType }
+}.get(instance) // Get this method
+
Tips
Use param { ... } to create a conditional method body, where the variable it is the Class type array instance of the current method parameter, and you can freely use Class all objects and their methods in.
The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result.
For more functions, please refer to FieldFinder.type, MethodFinder.param, MethodFinder.returnType, ConstructorFinder.param method.
You will notice that Test
extends BaseTest
, now we want to get the doBaseTask
method of BaseTest
, how do we do it without knowing the name of the super class?
Referring to the above find conditions, we only need to add a superClass
to the find conditions to achieve this function.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringClass)
+ // Just add this condition
+ superClass()
+}.get(instance).call("task_name")
+
At this time, we can get this method in the super class.
superClass
has a parameter isOnlySuperClass
, when set to true
, you can skip the current Class
and only find the super class of the current Class
.
Since we now know that the doBaseTask
method only exists in the super class, this condition can be added to save finding time.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringClass)
+ // Add a find condition
+ superClass(isOnlySuperClass = true)
+}.get(instance).call("task_name")
+
At this time, we can also get this method in the super class.
Once superClass
is set, it will automatically cycle backward to find out whether this method exists in all extends super classes, until it finds that the target has no super class (the extends is java.lang.Object
).
Tips
For more functions, please refer to MethodFinder.superClass, ConstructorFinder.superClass, FieldFinder.superClass methods.
Pay Attention
The currently founded Method can only find the Method of the current Class unless the superClass condition is specified, which is the default behavior of the Java Reflection API.
If we want to find a method name, but are not sure if it has changed in each release, we can use vague find.
Suppose we want to get the doTask
method in Class
, which can be implemented as follows.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name {
+ // Set name is case insensitive
+ it.equals("dotask", isIgnoreCase = true)
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
Knowing that there is currently only one doTask
method in Class
, we can also judge that the method name contains only the characters specified in it.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name {
+ // Only contains oTas
+ it.contains("oTas")
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
We can also judge based on the first and last strings.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name {
+ // Contains do at the beginning and Task at the end
+ it.startsWith("do") && it.endsWith("Task")
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
By observing that this method name contains only letters, we can add a precise search condition.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name {
+ // Start with do, end with Task, just letters
+ it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters()
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
Tips
Use name { ... } to create a conditional method body, where the variable it is the string of the current name, and you can freely use it in the extension method of NameRules function.
The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result.
For more functions, please refer to FieldFinder.name, MethodFinder.name methods and NameRules.
Sometimes, we may need to find a set of methods, constructors, and fields with the same characteristics in a Class
.
At this time, we can use relative condition matching to complete.
Based on the result of the find condition, we only need to replace get
with all
to get all the bytecodes that match the condition.
Suppose this time we want to get all methods in Class
with the number of method parameters in the range 1..3
, you can use the following implementation.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ paramCount(1..3)
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
The above example can be perfectly matched to the following 3 methods.
private void doTask(String taskName)
private void release(String taskName, Function<boolean, String> task, boolean isFinish)
private void b(String a)
If you want to define the conditions for the range of the number of parameters more freely, you can use the following implementation.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ paramCount { it < 3 }
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
The above example can be perfectly matched to the following 6 methods.
private static void init()
private void doTask(String taskName)
private void stop(String a)
private void getName(String a)
private void b()
private void b(String a)
By observing that there are two methods named b
in Class
, you can use the following implementation.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "b"
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
The above example can be perfectly matched to the following 2 methods.
private void b()
private void b(String a)
Tips
Use paramCount { ... } to create a conditional method body, where the variable it is the integer of the current number of parameters, and you can use it freely in the extension method of CountRules function in it.
The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result.
For more functions, please refer to MethodFinder.paramCount, ConstructorFinder.paramCount methods and CountRules.
Some methods and fields are statically implemented in Class
, at this time, we can call them without passing in an instance.
Suppose we want to get the contents of the static field TAG
this time.
The following example
Test::class.java.field {
+ name = "TAG"
+ type = StringClass
+}.get().string() // The type of Field is string and can be cast directly
+
Assuming that there is a non-static TAG
field with the same name in Class
, what should I do at this time?
Just add a filter.
The following example
Test::class.java.field {
+ name = "TAG"
+ type = StringClass
+ // This field to identify the lookup needs to be static
+ modifiers { isStatic }
+}.get().string() // The type of Field is string and can be cast directly
+
We can also call a static method called init
.
The following example
Test::class.java.method {
+ name = "init"
+ emptyParam()
+}.get().call()
+
Likewise, you can identify it as a static.
The following example
Test::class.java.method {
+ name = "init"
+ emptyParam()
+ // This method of identity find needs to be static
+ modifiers { isStatic }
+}.get().call()
+
Tips
Use modifiers { ... } to create a conditional method body, at which point you can freely use its functionality in ModifierRules.
The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result.
For more functions, please refer to FieldFinder.modifiers, MethodFinder.modifiers, ConstructorFinder.modifiers methods and ModifierRules.
You may have noticed that the example Class
given here has two obfuscated field names, both of which are a
, how do we get them at this time?
There are two options.
The first option is to determine the name and type of the field.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.field {
+ name = "a"
+ type = BooleanType
+}.get(instance).any() // Get a field named a with type Boolean
+
The second option is to determine where the type of the field is located.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.field {
+ type(BooleanType).index().first()
+}.get(instance).any() // Get the first field of type Boolean
+
In the above two cases, the corresponding field private boolean a
can be obtained.
Likewise, there are two obfuscated method names in this Class
, both of which are b
.
You can also have two options to get them.
The first option is to determine the method name and method parameters.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "b"
+ param(StringClass)
+}.get(instance).call("test_string") // Get the method whose name is b and whose parameter is [String]
+
The second option is to determine where the parameters of the method are located.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ param(StringClass).index().first()
+}.get(instance).call("test_string") // Get the method whose first method parameter is [String]
+
Since it is observed that this method is last in Class
, then we have an alternative.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ order().index().last()
+}.get(instance).call("test_string") // Get the last method of the current Class
+
Notice
Please try to avoid using order to filter bytecode subscripts, they may be indeterminate unless you are sure that its position in this Class must not change.
The methods of calling bytecode described above all need to use get(instance)
to call the corresponding method.
Is there a simpler way?
At this point, you can use the current
method on any instance to create a call space.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // Execute the doTask method
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+ // Execute the stop method
+ method {
+ name = "stop"
+ emptyParam()
+ }.call()
+ // Get name
+ val name = method { name = "getName" }.string()
+}
+
We can also use superClass
to call methods of the current Class
super class.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // Execute the doBaseTask method of the parent class
+ superClass().method {
+ name = "doBaseTask"
+ param(StringClass)
+ }.call("task_name")
+}
+
If you don't like to use a lambda to create the namespace of the current instance, you can use the current()
method directly.
The following example
// Assuming this is an instance of this Class, this Class cannot be obtained directly
+val instance = Test()
+// Execute the doTask method
+instance
+ .current()
+ .method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+// Execute the stop method
+instance
+ .current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// Get name
+val name = instance.current().method { name = "getName" }.string()
+
Likewise, consecutive calls can be made between them, but inline calls are not allowed.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+}.current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// Note that because current() returns the CurrentClass object itself
+// It CANNOT BE CALLED like the following
+instance.current().current()
+
For Field
instances, there is also a convenience method that can directly get the object of the instance where Field
is located.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // <Plan 1>
+ field {
+ name = "baseInstance"
+ }.current {
+ method {
+ name = "doBaseTask"
+ param(StringClass)
+ }.call("task_name")
+ }
+ // <Plan 2>
+ field {
+ name = "baseInstance"
+ }.current()
+ ?.method {
+ name = "doBaseTask"
+ param(StringClass)
+ }?.call("task_name")
+}
+
Notice
The above current method is equivalent to calling the field { ... }.any()?.current() method in CurrentClass for you.
If there is no CurrentClass calling field, you need to use field { ... }.get(instance).current() to call it.
The problem comes again, I want to use reflection to create the following instance and call the method in it, how to do it?
The following example
Test(true).doTask("task_name")
+
Usually, we can use the standard reflection API to call.
The following example
"com.demo.Test".toClass()
+ .getDeclaredConstructor(Boolean::class.java)
+ .apply { isAccessible = true }
+ .newInstance(true)
+ .apply {
+ javaClass
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(this, "task_name")
+ }
+
But I feel that this approach is very troublesome.
Is there a more concise way to call it?
At this time, we can also use the buildOf
method to create an instance.
The following example
"com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+}
+
If you want the buildOf
method to return the type of the current instance, you can include a type-generic declaration in it instead of using as
to cast
the target type.
In this case, the constructor of the instance itself is private, but the method inside is public, so we only need to create its constructor by reflection.
The following example
// Assume this Class can be obtained directly
+val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
+test.doTask("task_name")
+
Tips
For more functions, please refer to CurrentClass and Class.buildOf method.
Suppose there are three different versions of Class
, all of which are the same Class
for different versions of this app.
There is also a method doTask
in it, assuming they function the same.
The following example of version A
public class Test {
+
+ public void doTask() {
+ // ...
+ }
+}
+
The following example of version B
public class Test {
+
+ public void doTask(String taskName) {
+ // ...
+ }
+}
+
The following example of version C
public class Test {
+
+ public void doTask(String taskName, int type) {
+ // ...
+ }
+}
+
We need to get this same functionality of the doTask
method in a different version, how do we do it?
At this point, you can use RemedyPlan
to complete your needs.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+ method {
+ name = "doTask"
+ param(StringClass, IntType)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+}.wait(instance) {
+ // Get the result of the method
+}
+
Pay Attention
The method lookup result using RemedyPlan can no longer use get to get method instance, you should use wait method.
Also, you can continue to use RemedyPlan
while using Multiple Find.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+}.waitAll(instance) {
+ // Get the result of the method
+}
+
Tips
For more functions, please refer to MethodFinder.RemedyPlan, ConstructorFinder.RemedyPlan, FieldFinder.RemedyPlan .
Suppose there is a Class
with the same function in different versions of the current app but only the name of the Class
is different.
The following example of version A
public class ATest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
The following example of version B
public class BTest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
At this time, what should we do if we want to call the doTask
method in this Class
in each version?
The usual practice is to check if Class
exists.
The following example
// First find this Class
+val currentClass =
+ if("com.demo.ATest".hasClass()) "com.demo.ATest".toClass() else "com.demo.BTest".toClass()
+// Then look for this method and call
+currentClass.method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
I feel that this solution is very inelegant and cumbersome, then YukiReflection
provides you with a very convenient VariousClass
to solve this problem.
Now, you can get this Class
directly using the following methods.
The following example
VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
If the current Class
exists in the specified ClassLoader
, you can fill in your ClassLoader
in get
.
The following example
val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
If you are not sure that all Class
will be matched, you can use the getOrNull
method.
The following example
val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
+ name = "doTask"
+ emptyParam()
+}?.get()?.call()
+
Tips
For more functions, please refer to VariousClass.
In the process of reflection, we may encounter generic problems.
In the reflection processing of generics, YukiReflection
also provides a syntactic sugar that can be used anywhere.
For example we have the following generic class.
The following example
class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // ...
+ }
+}
+
When we want to get a Class
instance of the generic T
or R
in the current Class
, only the following implementation is required.
The following example
class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // Get the operation object of the current instance
+ // Get the Class instance of T, in the 0th position of the parameter
+ // The default value can not be written
+ val tClass = current().generic()?.argument()
+ // Get the Class instance of R, in parameter 1
+ val rClass = current().generic()?.argument(index = 1)
+ // You can also use the following syntax
+ current().generic {
+ // Get the Class instance of T
+ // In the 0th position of the parameter, the default value can be left blank
+ val tClass = argument()
+ // Get the Class instance of R, in parameter 1
+ val rClass = argument(index = 1)
+ }
+ }
+}
+
When we want to call this Class
externally, it can be implemented as follows.
The following example
// Assume this is the Class of T
+class TI {
+
+ fun foo() {
+ // ...
+ }
+}
+// Assume this is an instance of T
+val tInstance: TI? = ...
+// Get the Class instance of T
+// In the 0th position of the parameter, the default value can be left blank
+// And get the method foo and call it
+TestGeneric::class.java.generic()?.argument()?.method {
+ name = "foo"
+ emptyParam()
+}?.get(tInstance)?.invoke<TI>()
+
Tips
For more functions, please refer to CurrentClass.generic, Class.generic methods and GenericClass.
Here are some misunderstandings that may be encountered during use for reference.
In find conditions you can only use index
function once except order
.
The following example
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ // Wrong usage, please keep only one index method
+ returnType(StringClass).index(num = 1)
+}
+
The following find conditions can be used without any problems.
The following example
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ order().index(num = 1)
+}
+
In common method find conditions, even methods without parameters need to set find conditions.
Suppose we have the following Class
.
The following example
public class TestFoo {
+
+ public void foo(String string) {
+ // ...
+ }
+
+ public void foo() {
+ // ...
+ }
+}
+
We want to get the public void foo()
method, which can be written as follows.
The following example
TestFoo::class.java.method {
+ name = "foo"
+}
+
However, the above example is wrong.
You will find two foo
methods in this Class
, one of which takes a method parameter.
Since the above example does not set the find conditions for param
, the result will be the first method public void foo(String string)
that matches the name and matches the bytecode order, not the last method we need.
This is a frequent error, without method parameters, you will lose the use of method parameter find conditions.
The correct usage is as follows.
The following example
TestFoo::class.java.method {
+ name = "foo"
+ // ✅ Correct usage, add detailed filter conditions
+ emptyParam()
+}
+
At this point, the above example will perfectly match the public void foo()
method.
Compatibility Notes
In the past historical versions of the API, it was allowed to match the method without writing the default matching no-parameter method, but the latest version has corrected this problem, please make sure that you are using the latest API version.
In the find conditions for constructors, even constructors without parameters need to set find conditions.
Suppose we have the following Class
.
The following example
public class TestFoo {
+
+ public TestFoo() {
+ // ...
+ }
+}
+
To get the public TestFoo()
constructor, we must write it in the following form.
The following example
TestFoo::class.java.constructor { emptyParam() }
+
The above example can successfully obtain the public TestFoo()
constructor.
If you write constructor()
and miss emptyParam()
, the result found at this time will be the first one in bytecode order, may not be parameterless.
Compatibility Notes
In past historical versions of the API, if the constructor does not fill in any search parameters, the constructor will not be found directly.
This is a BUG and has been fixed in the latest version, please make sure you are using the latest API version.
API Behavior Changes
In 1.2.0 and later versions, the behavior of constructor() is no longer constructor { emptyParam() } but constructor {}, please pay attention to the behavior change reasonably adjust the find parameters.
Without setting find conditions, using field()
, constructor()
, method()
will return all members under the current Class
.
Using get(...)
or give()
will only get the first bit in bytecode order.
The following example
Test::class.java.field().get(...)
+Test::class.java.method().give()
+
If you want to get all members, you can use all(...)
or giveAll()
The following example
Test::class.java.field().all(...)
+Test::class.java.method().giveAll()
+
Compatibility Notes
In past historical versions of the API, failure to set find conditions will throw an exception.
This feature was added in 1.2.0 and later versions.
In the bytecode call result, the cast method can only specify the type corresponding to the bytecode.
For example we want to get a field of type Boolean
and cast it to String
.
The following is the wrong way to use it.
The following example
field {
+ name = "test"
+ type = BooleanType
+}.get().string() // Wrong usage, must be cast to the bytecode target type
+
The following is the correct way to use it.
The following example
field {
+ name = "test"
+ type = BooleanType
+}.get().boolean().toString() // ✅ The correct way to use, get the type and then convert
+
When find methods and fields, we usually need to specify the type in find conditions.
The following example
field {
+ name = "test"
+ type = Boolean::class.javaPrimitiveType
+}
+
Expressing the type of Boolean::class.javaPrimitiveType
in Kotlin is very long and inconvenient.
Therefore, YukiReflection
encapsulates common type calls for developers, including Android related types and Java common types and primitive type keywords.
At this time, the above type can be written in the following form.
The following example
field {
+ name = "test"
+ type = BooleanType
+}
+
The primitive type keywords in common Java types have been encapsulated as Type(Class Name) + Type, such as IntType
, FloatType
(their bytecode types are int
, float
).
Correspondingly, array types also have convenient usage methods, assuming we want to get an array of type String[]
.
You need to write java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
to get this type.
Does it feel very troublesome, at this time we can use the method ArrayClass(StringClass)
to get this type.
At the same time, since String
is a common type, you can also directly use StringArrayClass
to get this type.
The methods found in some common requirements have their corresponding encapsulation types for use, in the format Type(Class Name) + Class.
The following are wrapper names for some special case types in Java represented in YukiReflection
.
void
→ UnitType
java.lang.Void
→ UnitClass
java.lang.Object
→ AnyClass
java.lang.Integer
→ IntClass
java.lang.Character
→ CharClass
Notice
Encapsulating types with Type(Class Name) + Type will and only be represented as Java primitive type keywords.
Since the concept of primitive types does not exist in Kotlin, they will all be defined as KClass.
There are 9 primitive type keywords in Java, of which 8 are primitive type, namely boolean, char, byte, short , int, float, long, double, of which the void type is a special case.
At the same time, they all have their own corresponding package types in Java, such as java.lang.Boolean, java.lang.Integer, these types are unequal, Please note the distinction.
Similarly, arrays also have corresponding wrapper types, which also need to be distinguished from Java primitive type keywords.
For example, the encapsulation type of byte[] is ByteArrayType or ArrayClass(ByteType), and the encapsulation type of Byte[] is ByteArrayClass or ArrayClass(ByteClass), these types are also unequal.
Tips
For more types, see ComponentTypeFactory, GraphicsTypeFactory, ViewTypeFactory, VariableTypeFactory.
At the same time, you are welcome to contribute more commonly used types.
`,344);function b(F,g){const o=e("Badge"),p=e("ExternalLinkIcon");return c(),i("div",null,[d,s("h3",y,[A,n(" Vague Search "),l(o,{type:"tip",text:"Beta",vertical:"middle"})]),u,s("div",D,[B,C,s("p",null,[n("We welcome all developers to start using "),s("a",m,[n("DexKit"),l(p)]),n(", which is a high-performance runtime parsing library for "),v,n(" implemented in C++, which is more efficient than the Java layer in terms of performance, efficient and excellent, it is still in the development stage, your valuable suggestions are welcome.")])]),h])}const k=t(r,[["render",b],["__file","features.html.vue"]]);export{k as default}; diff --git a/assets/features.html-VU512ZaF.js b/assets/features.html-VU512ZaF.js new file mode 100644 index 0000000..ca24388 --- /dev/null +++ b/assets/features.html-VU512ZaF.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-c557cfcc","path":"/en/api/features.html","title":"Features","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Class Extensions","slug":"class-extensions","link":"#class-extensions","children":[{"level":3,"title":"Object Conversion","slug":"object-conversion","link":"#object-conversion","children":[]},{"level":3,"title":"Lazy Loading","slug":"lazy-loading","link":"#lazy-loading","children":[]},{"level":3,"title":"Existential Judgment","slug":"existential-judgment","link":"#existential-judgment","children":[]},{"level":3,"title":"Vague Search","slug":"vague-search","link":"#vague-search","children":[]}]},{"level":2,"title":"Member Extensions","slug":"member-extensions","link":"#member-extensions","children":[{"level":3,"title":"Find and Reflection","slug":"find-and-reflection","link":"#find-and-reflection","children":[]},{"level":3,"title":"Optional Find Conditions","slug":"optional-find-conditions","link":"#optional-find-conditions","children":[]},{"level":3,"title":"Find in Super Class","slug":"find-in-super-class","link":"#find-in-super-class","children":[]},{"level":3,"title":"Vague Find","slug":"vague-find","link":"#vague-find","children":[]},{"level":3,"title":"Multiple Find","slug":"multiple-find","link":"#multiple-find","children":[]},{"level":3,"title":"Static Bytecode","slug":"static-bytecode","link":"#static-bytecode","children":[]},{"level":3,"title":"Obfuscated Bytecode","slug":"obfuscated-bytecode","link":"#obfuscated-bytecode","children":[]},{"level":3,"title":"Directly Called","slug":"directly-called","link":"#directly-called","children":[]},{"level":3,"title":"Find Again","slug":"find-again","link":"#find-again","children":[]},{"level":3,"title":"Relative Matching","slug":"relative-matching","link":"#relative-matching","children":[]},{"level":3,"title":"Calling Generics","slug":"calling-generics","link":"#calling-generics","children":[]},{"level":3,"title":"Pay Attention of Trap","slug":"pay-attention-of-trap","link":"#pay-attention-of-trap","children":[]}]},{"level":2,"title":"Common Type Extensions","slug":"common-type-extensions","link":"#common-type-extensions","children":[]}],"git":{"updatedTime":1696670135000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":8}]},"filePathRelative":"en/api/features.md"}');export{e as data}; diff --git a/assets/features.html-tu9AQPUC.js b/assets/features.html-tu9AQPUC.js new file mode 100644 index 0000000..4b41ed9 --- /dev/null +++ b/assets/features.html-tu9AQPUC.js @@ -0,0 +1,769 @@ +import{_ as c,r as l,o as t,c as r,b as s,d as n,e,a}from"./app-Un_zyw_U.js";const i={},d=a(`这里包含了
YukiReflection
全部核心功能的用法示例。
这里是 Class 对象自身相关的扩展功能。
假设我们要得到一个不能直接调用的 Class
,通常情况下,我们可以使用标准的反射 API 去查找这个 Class
。
示例如下
// 默认 ClassLoader 环境下的 Class
+var instance = Class.forName("com.demo.Test")
+// 指定 ClassLoader 环境下的 Class
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var instance = customClassLoader?.loadClass("com.demo.Test")
+
这种写法大概不是很友好,此时 YukiReflection
就为你提供了一个可在任意地方使用的语法糖。
以上写法换做 YukiReflection
可写作如下形式。
示例如下
// 直接得到这个 Class
+var instance = "com.demo.Test".toClass()
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var instance = "com.demo.Test".toClass(customClassLoader)
+
如果当前 Class
并不存在,使用上述方法会抛出异常,如果你不确定 Class
是否存在,可以参考下面的解决方案。
示例如下
// 直接得到这个 Class
+// 得不到时结果会为 null 但不会抛出异常
+var instance = "com.demo.Test".toClassOrNull()
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+// 得不到时结果会为 null 但不会抛出异常
+var instance = "com.demo.Test".toClassOrNull(customClassLoader)
+
我们还可以通过映射来得到一个存在的 Class
对象。
示例如下
// 假设这个 Class 是能够被直接得到的
+var instance = classOf<Test>()
+// 我们同样可以自定义 Class 所在的 ClassLoader,这对于 stub 来说非常有效
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var instance = classOf<Test>(customClassLoader)
+
小提示
更多功能请参考 classOf、String.toClass、String.toClassOrNull 方法。
假设我们要得到一个不能直接调用的 Class
,但是我们也不是立刻就需要这个 Class
。
这个时候,你可以使用 lazyClass
来完成这个功能。
示例如下
// 延迟装载这个 Class
+val instance by lazyClass("com.demo.Test")
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+val instance by lazyClass("com.demo.Test") { customClassLoader }
+// 在适当的时候调用这个 Class
+instance.method {
+ // ...
+}
+
如果当前 Class
并不存在,使用上述方法会抛出异常,如果你不确定 Class
是否存在,可以参考下面的解决方案。
示例如下
// 延迟装载这个 Class
+// 得不到时结果会为 null 但不会抛出异常
+val instance by lazyClassOrNull("com.demo.Test")
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+// 得不到时结果会为 null 但不会抛出异常
+val instance by lazyClassOrNull("com.demo.Test") { customClassLoader }
+// 在适当的时候调用这个 Class
+instance?.method {
+ // ...
+}
+
小提示
更多功能请参考 lazyClass、lazyClassOrNull 方法。
假设我们要判断一个 Class
是否存在,通常情况下,我们可以使用标准的反射 API 去查找这个 Class
通过异常来判断是否存在。
示例如下
// 默认 ClassLoader 环境下的 Class
+var isExist = try {
+ Class.forName("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+// 指定 ClassLoader 环境下的 Class
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var isExist = try {
+ customClassLoader?.loadClass("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+
这种写法大概不是很友好,此时 YukiReflection
就为你提供了一个可在任意地方使用的语法糖。
以上写法换做 YukiReflection
可写作如下形式。
示例如下
// 判断这个 Class 是否存在
+var isExist = "com.demo.Test".hasClass()
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var isExist = "com.demo.Test".hasClass(customClassLoader)
+
小提示
更多功能请参考 String.hasClass 方法。
在 R8 等工具混淆后的当前 APP Dex 中的 Class
名称将会难以分辨,且不确定其正确位置,不能直接通过 对象转换 来得到。
此时就有了 DexClassFinder
,它的作用是通过需要查找的 Class
中的字节码特征来确定这个 Class
的实例。
注意
此功能仅适用于 Android 平台。
目前 DexClassFinder 的功能尚在试验阶段,由于仅通过 Java 层实现查找功能,在当前 APP Class 过多时性能可能不能达到最佳水平,如果发生查找不到、定位有误的问题欢迎向我们反馈。
由于是反射层面的 API,目前它只能通过类与成员的特征来定位指定的 Class,不能通过指定字节码中的字符串和方法内容特征来进行定位。
查找 Class 的速度取决于当前设备的性能,目前主流的移动端处理器在 10~15w 数量的 Class 中条件不算复杂的情况下大概在 3~10s 区间,条件稍微复杂的情况下最快速度能达到 25s 以内,匹配到的同类型 Class 越多速度越慢。
下面是一个简单的用法示例。
假设下面这个 Class
是我们想要得到的,其中的名称经过了混淆,在每个版本可能都不一样。
示例如下
package com.demo;
+
+public class a extends Activity implements Serializable {
+
+ public a(String var1) {
+ // ...
+ }
+
+ private String a;
+
+ private String b;
+
+ private boolean a;
+
+ protected void onCreate(Bundle var1) {
+ // ...
+ }
+
+ private static void a(String var1) {
+ // ...
+ }
+
+ private String a(boolean var1, String var2) {
+ // ...
+ }
+
+ private void a() {
+ // ...
+ }
+
+ public void a(boolean var1, a var2, b var3, String var4) {
+ // ...
+ }
+}
+
此时,我们想得到这个 Class
,可以直接使用 ClassLoader.searchClass
方法。
下方演示的条件中每一个都是可选的,条件越复杂定位越精确,同时性能也会越差。
示例如下
searchClass {
+ // 从指定的包名范围开始查找,实际使用时,你可以同时指定多个包名范围
+ from("com.demo")
+ // 指定当前 Class 的 getSimpleName 的结果,你可以直接对这个字符串进行逻辑判断
+ // 这里我们不确定它的名称是不是 a,可以只判断字符串长度
+ simpleName { it.length == 1 }
+ // 指定继承的父类对象,如果是存在的 stub,可以直接用泛型表示
+ extends<Activity>()
+ // 指定继承的父类对象,可以直接写为完整类名,你还可以同时指定多个
+ extends("android.app.Activity")
+ // 指定实现的接口,如果是存在的 stub,可以直接用泛型表示
+ implements<Serializable>()
+ // 指定实现的接口,可以直接写为完整类名,你还可以同时指定多个
+ implements("java.io.Serializable")
+ // 指定构造方法的类型与样式,以及在当前类中存在的个数 count
+ constructor { param(StringClass) }.count(num = 1)
+ // 指定变量的类型与样式,以及在当前类中存在的个数 count
+ field { type = StringClass }.count(num = 2)
+ // 指定变量的类型与样式,以及在当前类中存在的个数 count
+ field { type = BooleanType }.count(num = 1)
+ // 直接指定所有变量在当前类中存在的个数 count
+ field().count(num = 3)
+ // 如果你认为变量的个数是不确定的,还可以使用如下自定义条件
+ field().count(1..3)
+ field().count { it >= 3 }
+ // 指定方法的类型与样式,以及在当前类中存在的个数 count
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count
+ method {
+ modifiers { isStatic && isPrivate }
+ param(StringClass)
+ returnType = UnitType
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, StringClass)
+ returnType = StringClass
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ emptyParam()
+ returnType = UnitType
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符和模糊类型 VagueType,以及在当前类中存在的个数 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, VagueType, VagueType, StringClass)
+ returnType = UnitType
+ }.count(num = 1)
+ // 直接指定所有方法在当前类中存在的个数 count
+ method().count(num = 5)
+ // 如果你认为方法的个数是不确定的,还可以使用如下自定义条件
+ method().count(1..5)
+ method().count { it >= 5 }
+ // 直接指定所有成员 (Member) 在当前类中存在的个数 count
+ // 成员包括:Field (变量)、Method (方法)、Constructor (构造方法)
+ member().count(num = 9)
+ // 所有成员中一定存在一个 static 修饰符,可以这样加入此条件
+ member {
+ modifiers { isStatic }
+ }
+}.get() // 得到这个 Class 本身的实例,找不到会返回 null
+
小提示
上述用法中对于 Field、Method、Constructor 的条件用法与 Member 扩展 中的相关用法是一致的,仅有小部分区别。
更多功能请参考 MemberRules、FieldRules、MethodRules、ConstructorRules。
默认情况下 DexClassFinder
会使用同步方式查找 Class
,会阻塞当前线程直到找到或找不到发生异常为止,若查找消耗的时间过长,可能会导致当前 APP 发生 ANR 问题。
针对上述问题,我们可以启用异步,只需要加入参数 async = true
,这将不需要你再次启动一个线程,API 已帮你处理好相关问题。
注意
若要使用此功能,你需要在方法参数首位传入当前 APP 的 Context。
对于异步情况下你需要使用 wait 方法来得到结果,get 方法将不再起作用。
示例如下
val context: Context // 假设这就是当前 APP 的 Context
+searchClass(context, async = true) {
+ // ...
+}.wait { class1 ->
+ // 得到异步结果
+}
+searchClass(context, async = true) {
+ // ...
+}.wait { class2 ->
+ // 得到异步结果
+}
+
这样我们的查找过程就是异步运行了,它将不会阻塞主线程,每个查找都将在单独的线程同时进行,可达到并行任务的效果。
由于每次重新打开当前 APP 都会重新进行查找,在当前 APP 版本不变的情况下这是一种重复性能浪费。
此时我们可以通过指定 name
参数来对当前 APP 版本的查找结果进行本地缓存,下一次将直接从本地缓存中读取查找到的类名。
本地缓存使用的是 SharedPreferences
,它将被保存到当前 APP 的数据目录中,在当前 APP 版本更新后会重新进行缓存。
启用本地缓存后,将同时设置 async = true
,你可以不需要再手动进行设置。
注意
若要使用此功能,你需要在方法参数首位传入当前 APP 的 Context。
示例如下
val context: Context // 假设这就是当前 APP 的 Context
+searchClass(context, name = "com.demo.class1") {
+ // ...
+}.wait { class1 ->
+ // 得到异步结果
+}
+searchClass(context, name = "com.demo.class2") {
+ // ...
+}.wait { class2 ->
+ // 得到异步结果
+}
+
如果你想手动清除本地缓存,可以使用如下方法清除当前 APP 版本的缓存。
示例如下
val context: Context // 假设这就是当前 APP 的 Context
+DexClassFinder.clearCache(context)
+
你还可以清除指定版本的 APP 缓存。
示例如下
val context: Context // 假设这就是当前 APP 的 Context
+DexClassFinder.clearCache(context, versionName = "1.0", versionCode = 1)
+
如果你需要使用固定的条件同时查找一组 Class
,那么你只需要使用 all
或 waitAll
方法来得到结果。
// 同步查找,使用 all 得到条件全部查找到的结果
+searchClass {
+ // ...
+}.all().forEach { clazz ->
+ // 得到每个结果
+}
+// 同步查找,使用 all { ... } 遍历每个结果
+searchClass {
+ // ...
+}.all { clazz ->
+ // 得到每个结果
+}
+// 异步查找,使用 waitAll 得到条件全部查找到的结果
+val context: Context // 假设这就是当前 APP 的 Context
+searchClass(context, async = true) {
+ // ...
+}.waitAll { classes ->
+ classes.forEach {
+ // 得到每个结果
+ }
+}
+
小提示
更多功能请参考 ClassLoader.searchClass 方法。
这里是 Class 字节码成员变量 Field、Method、Constructor 相关的扩展功能。
小提示
Member 是 Field、Method、Constructor 的接口描述对象,它在 Java 反射中为 Class 中字节码成员的总称。
假设有一个这样的 Class
。
示例如下
package com.demo;
+
+public class BaseTest {
+
+ public BaseTest() {
+ // ...
+ }
+
+ public BaseTest(boolean isInit) {
+ // ...
+ }
+
+ private void doBaseTask(String taskName) {
+ // ...
+ }
+}
+
package com.demo;
+
+public class Test extends BaseTest {
+
+ public Test() {
+ // ...
+ }
+
+ public Test(boolean isInit) {
+ // ...
+ }
+
+ private static TAG = "Test";
+
+ private BaseTest baseInstance;
+
+ private String a;
+
+ private boolean a;
+
+ private boolean isTaskRunning = false;
+
+ private static void init() {
+ // ...
+ }
+
+ private void doTask(String taskName) {
+ // ...
+ }
+
+ private void release(String taskName, Function<boolean, String> task, boolean isFinish) {
+ // ...
+ }
+
+ private void stop() {
+ // ...
+ }
+
+ private String getName() {
+ // ...
+ }
+
+ private void b() {
+ // ...
+ }
+
+ private void b(String a) {
+ // ...
+ }
+}
+
假设我们要得到 Test
(以下统称“当前 Class
”)的 doTask
方法并执行,通常情况下,我们可以使用标准的反射 API 去查找这个方法。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用反射 API 调用并执行
+Test::class.java
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(instance, "task_name")
+
这种写法大概不是很友好,此时 YukiReflection
就为你提供了一个可在任意地方使用的语法糖。
以上写法换做 YukiReflection
可写作如下形式。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doTask"
+ param(StringClass)
+}.get(instance).call("task_name")
+
小提示
更多功能请参考 MethodFinder。
同样地,我们需要得到 isTaskRunning
变量也可以写作如下形式。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.field {
+ name = "isTaskRunning"
+ type = BooleanType
+}.get(instance).any() // any 为 Field 的任意类型实例化对象
+
小提示
更多功能请参考 FieldFinder。
也许你还想得到当前 Class
的构造方法,同样可以实现。
示例如下
Test::class.java.constructor {
+ param(BooleanType)
+}.get().call(true) // 可创建一个新的实例
+
若想得到的是 Class
的无参构造方法,可写作如下形式。
示例如下
Test::class.java.constructor().get().call() // 可创建一个新的实例
+
小提示
更多功能请参考 ConstructorFinder。
假设我们要得到 Class
中的 getName
方法,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+ returnType = StringClass
+}.get(instance).string() // 得到方法的结果
+
通过观察发现,这个 Class
中只有一个名为 getName
的方法,那我们可不可以再简单一点呢?
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+}.get(instance).string() // 得到方法的结果
+
是的,对于确切不会变化的方法,你可以精简查找条件。
在只使用 get
或 wait
方法得到结果时 YukiReflection
会默认按照字节码顺序匹配第一个查找到的结果。
问题又来了,这个 Class
中有一个 release
方法,但是它的方法参数很长,而且部分类型可能无法直接得到。
通常情况下我们会使用 param(...)
来查找这个方法,但是有没有更简单的方法呢。
此时,在确定方法唯一性后,你可以使用 paramCount
来查找到这个方法。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "release"
+ // 此时我们不必确定方法参数具体类型,写个数就好
+ paramCount = 3
+}.get(instance) // 得到这个方法
+
上述示例虽然能够匹配成功,但是不精确,此时你还可以使用 VagueType
来填充你不想填写的方法参数类型。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "release"
+ // 使用 VagueType 来填充不想填写的类型,同时保证其它类型能够匹配
+ param(StringClass, VagueType, BooleanType)
+}.get(instance) // 得到这个方法
+
如果你并不确定每一个参数的类型,你可以通过 param { ... }
方法来创建一个条件方法体。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "release"
+ // 得到 it (Class) 方法参数类型数组实例来仅判断已知的类型和它的位置
+ param { it[0] == StringClass && it[2] == BooleanType }
+}.get(instance) // 得到这个方法
+
小提示
使用 param { ... } 创建一个条件方法体,其中的变量 it 即当前方法参数的 Class 类型数组实例,此时你就可以自由使用 Class 中的所有对象及其方法。
方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。
更多功能请参考 FieldFinder.type、MethodFinder.param、MethodFinder.returnType、ConstructorFinder.param 方法。
你会注意到 Test
继承于 BaseTest
,现在我们想得到 BaseTest
的 doBaseTask
方法,在不知道父类名称的情况下,要怎么做呢?
参照上面的查找条件,我们只需要在查找条件中加入一个 superClass
即可实现这个功能。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringClass)
+ // 只需要添加这个条件
+ superClass()
+}.get(instance).call("task_name")
+
这个时候我们就可以在父类中取到这个方法了。
superClass
有一个参数为 isOnlySuperClass
,设置为 true
后,可以跳过当前 Class
仅查找当前 Class
的父类。
由于我们现在已知 doBaseTask
方法只存在于父类,可以加上这个条件节省查找时间。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringClass)
+ // 加入一个查找条件
+ superClass(isOnlySuperClass = true)
+}.get(instance).call("task_name")
+
这个时候我们同样可以得到父类中的这个方法。
superClass
一旦设置就会自动循环向后查找全部继承的父类中是否有这个方法,直到查找到目标没有父类(继承关系为 java.lang.Object
)为止。
特别注意
当前查找的 Method 除非指定 superClass 条件,否则只能查找到当前 Class 的 Method,这是 Java 反射 API 的默认行为。
如果我们想查找一个方法名称,但是又不确定它在每个版本中是否发生变化,此时我们就可以使用模糊查找功能。
假设我们要得到 Class
中的 doTask
方法,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name {
+ // 设置名称不区分大小写
+ it.equals("dotask", isIgnoreCase = true)
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
已知当前 Class
中仅有一个 doTask
方法,我们还可以判断方法名称仅包含其中指定的字符。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name {
+ // 仅包含 oTas
+ it.contains("oTas")
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
我们还可以根据首尾字符串进行判断。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name {
+ // 开头包含 do,结尾包含 Task
+ it.startsWith("do") && it.endsWith("Task")
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
通过观察发现这个方法名称中只包含字母,我们还可以再增加一个精确的查找条件。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name {
+ // 开头包含 do,结尾包含 Task,仅包含字母
+ it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters()
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
小提示
使用 name { ... } 创建一个条件方法体,其中的变量 it 即当前名称的字符串,此时你就可以在 NameRules 的扩展方法中自由使用其中的功能。
方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。
更多功能请参考 FieldFinder.name、MethodFinder.name 方法以及 NameRules。
有些时候,我们可能需要查找一个 Class
中具有相同特征的一组方法、构造方法、变量,此时,我们就可以利用相对条件匹配来完成。
在查找条件结果的基础上,我们只需要把 get
换为 all
即可得到匹配条件的全部字节码。
假设这次我们要得到 Class
中方法参数个数范围在 1..3
的全部方法,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ paramCount(1..3)
+}.all(instance).forEach { instance ->
+ // 调用执行每个方法
+ instance.call(...)
+}
+
上述示例可完美匹配到如下 3 个方法。
private void doTask(String taskName)
private void release(String taskName, Function<boolean, String> task, boolean isFinish)
private void b(String a)
如果你想更加自由地定义参数个数范围的条件,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ paramCount { it < 3 }
+}.all(instance).forEach { instance ->
+ // 调用执行每个方法
+ instance.call(...)
+}
+
上述示例可完美匹配到如下 6 个方法。
private static void init()
private void doTask(String taskName)
private void stop(String a)
private void getName(String a)
private void b()
private void b(String a)
通过观察 Class
中有两个名称为 b
的方法,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "b"
+}.all(instance).forEach { instance ->
+ // 调用执行每个方法
+ instance.call(...)
+}
+
上述示例可完美匹配到如下 2 个方法。
private void b()
private void b(String a)
小提示
使用 paramCount { ... } 创建一个条件方法体,其中的变量 it 即当前参数个数的整数,此时你就可以在 CountRules 的扩展方法中自由使用其中的功能。
方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。
更多功能请参考 MethodFinder.paramCount、ConstructorFinder.paramCount 方法以及 CountRules。
有些方法和变量在 Class
中是静态的实现,这个时候,我们不需要传入实例就可以调用它们。
假设我们这次要得到静态变量 TAG
的内容。
示例如下
Test::class.java.field {
+ name = "TAG"
+ type = StringClass
+}.get().string() // Field 的类型是字符串,可直接进行 cast
+
假设 Class
中存在同名的非静态 TAG
变量,这个时候怎么办呢?
加入一个筛选条件即可。
示例如下
Test::class.java.field {
+ name = "TAG"
+ type = StringClass
+ // 标识查找的这个变量需要是静态
+ modifiers { isStatic }
+}.get().string() // Field 的类型是字符串,可直接进行 cast
+
我们还可以调用名为 init
的静态方法。
示例如下
Test::class.java.method {
+ name = "init"
+ emptyParam()
+}.get().call()
+
同样地,你可以标识它是一个静态。
示例如下
Test::class.java.method {
+ name = "init"
+ emptyParam()
+ // 标识查找的这个方法需要是静态
+ modifiers { isStatic }
+}.get().call()
+
小提示
使用 modifiers { ... } 创建一个条件方法体,此时你就可以在 ModifierRules 中自由使用其中的功能。
方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。
更多功能请参考 FieldFinder.modifiers、MethodFinder.modifiers、ConstructorFinder.modifiers 方法以及 ModifierRules。
你可能已经注意到了,这里给出的示例 Class
中有两个混淆的变量名称,它们都是 a
,这个时候我们要怎么得到它们呢?
有两种方案。
第一种方案,确定变量的名称和类型。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.field {
+ name = "a"
+ type = BooleanType
+}.get(instance).any() // 得到名称为 a 类型为 Boolean 的变量
+
第二种方案,确定变量的类型所在的位置。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.field {
+ type(BooleanType).index().first()
+}.get(instance).any() // 得到第一个类型为 Boolean 的变量
+
以上两种情况均可得到对应的变量 private boolean a
。
同样地,这个 Class
中也有两个混淆的方法名称,它们都是 b
。
你也可以有两种方案来得到它们。
第一种方案,确定方法的名称和方法参数。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "b"
+ param(StringClass)
+}.get(instance).call("test_string") // 得到名称为 b 方法参数为 [String] 的方法
+
第二种方案,确定方法的参数所在的位置。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ param(StringClass).index().first()
+}.get(instance).call("test_string") // 得到第一个方法参数为 [String] 的方法
+
由于观察到这个方法在 Class
的最后一个,那我们还有一个备选方案。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ order().index().last()
+}.get(instance).call("test_string") // 得到当前 Class 的最后一个方法
+
注意
请尽量避免使用 order 来筛选字节码的下标,它们可能是不确定的,除非你确定它在这个 Class 中的位置一定不会变。
上面介绍的调用字节码的方法都需要使用 get(instance)
才能调用对应的方法,有没有简单一点的办法呢?
此时,你可以在任意实例上使用 current
方法来创建一个调用空间。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ // 执行 doTask 方法
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+ // 执行 stop 方法
+ method {
+ name = "stop"
+ emptyParam()
+ }.call()
+ // 得到 name
+ val name = method { name = "getName" }.string()
+}
+
我们还可以用 superClass
调用当前 Class
父类的方法。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ // 执行父类的 doBaseTask 方法
+ superClass().method {
+ name = "doBaseTask"
+ param(StringClass)
+ }.call("task_name")
+}
+
如果你不喜欢使用一个大括号的调用域来创建当前实例的命名空间,你可以直接使用 current()
方法。
示例如下
// 假设这就是这个 Class 的实例,这个 Class 是不能被直接得到的
+val instance = Test()
+// 执行 doTask 方法
+instance
+ .current()
+ .method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+// 执行 stop 方法
+instance
+ .current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// 得到 name
+val name = instance.current().method { name = "getName" }.string()
+
同样地,它们之间可以连续调用,但不允许内联调用。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+}.current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// 注意,因为 current() 返回的是 CurrentClass 自身对象,所以不能像下面这样调用
+instance.current().current()
+
针对 Field
实例,还有一个便捷的方法,可以直接获取 Field
所在实例的对象。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ // <方案1>
+ field {
+ name = "baseInstance"
+ }.current {
+ method {
+ name = "doBaseTask"
+ param(StringClass)
+ }.call("task_name")
+ }
+ // <方案2>
+ field {
+ name = "baseInstance"
+ }.current()
+ ?.method {
+ name = "doBaseTask"
+ param(StringClass)
+ }?.call("task_name")
+}
+
注意
上述 current 方法相当于帮你调用了 CurrentClass 中的 field { ... }.any()?.current() 方法。
若不存在 CurrentClass 调用域,你需要使用 field { ... }.get(instance).current() 来进行调用。
问题又来了,我想使用反射的方式创建如下的实例并调用其中的方法,该怎么做呢?
示例如下
Test(true).doTask("task_name")
+
通常情况下,我们可以使用标准的反射 API 来调用。
示例如下
"com.demo.Test".toClass()
+ .getDeclaredConstructor(Boolean::class.java)
+ .apply { isAccessible = true }
+ .newInstance(true)
+ .apply {
+ javaClass
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(this, "task_name")
+ }
+
但是感觉这种做法好麻烦,有没有更简洁的调用方法呢?
这个时候,我们还可以借助 buildOf
方法来创建一个实例。
示例如下
"com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+}
+
若你希望 buildOf
方法返回当前实例的类型,你可以在其中加入类型泛型声明,而无需使用 as
来 cast
目标类型。
这种情况多用于实例本身的构造方法是私有的,但是里面的方法是公有的,这样我们只需要对其构造方法进行反射创建即可。
示例如下
// 假设这个 Class 是能够直接被得到的
+val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
+test.doTask("task_name")
+
小提示
更多功能请参考 CurrentClass 以及 Class.buildOf 方法。
假设有三个不同版本的 Class
,它们都是这个 APP 不同版本相同的 Class
。
这里面同样都有一个方法 doTask
,假设它们的功能是一样的。
版本 A 示例如下
public class Test {
+
+ public void doTask() {
+ // ...
+ }
+}
+
版本 B 示例如下
public class Test {
+
+ public void doTask(String taskName) {
+ // ...
+ }
+}
+
版本 C 示例如下
public class Test {
+
+ public void doTask(String taskName, int type) {
+ // ...
+ }
+}
+
我们需要在不同的版本中得到这个相同功能的 doTask
方法,要怎么做呢?
此时,你可以使用 RemedyPlan
完成你的需求。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+ method {
+ name = "doTask"
+ param(StringClass, IntType)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+}.wait(instance) {
+ // 得到方法的结果
+}
+
特别注意
使用了 RemedyPlan 的方法查找结果不能再使用 get 的方式得到方法实例,应当使用 wait 方法。
另外,你还可以在使用 多重查找 的情况下继续使用 RemedyPlan
。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+}.waitAll(instance) {
+ // 得到方法的结果
+}
+
假设当前 APP 中不同版本中存在功能相同的 Class
但仅有 Class
的名称不一样。
版本 A 示例如下
public class ATest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
版本 B 示例如下
public class BTest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
这个时候我们想在每个版本都调用这个 Class
里的 doTask
方法该怎么做呢?
通常做法是判断 Class
是否存在。
示例如下
// 首先查找到这个 Class
+val currentClass =
+ if("com.demo.ATest".hasClass()) "com.demo.ATest".toClass() else "com.demo.BTest".toClass()
+// 然后再查找这个方法并调用
+currentClass.method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
感觉这种方案非常的不优雅且繁琐,那么此时 YukiReflection
就为你提供了一个非常方便的 VariousClass
专门来解决这个问题。
现在,你可以直接使用以下方式获取到这个 Class
。
示例如下
VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
若当前 Class
在指定的 ClassLoader
中存在,你可以在 get
中填入你的 ClassLoader
。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
若你不确定所有的 Class
一定会被匹配到,你可以使用 getOrNull
方法。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
+ name = "doTask"
+ emptyParam()
+}?.get()?.call()
+
小提示
更多功能请参考 VariousClass。
在反射过程中,我们可能会遇到泛型问题,在泛型的反射处理上,YukiReflection
同样提供了一个可在任意地方使用的语法糖。
例如我们有如下的泛型类。
示例如下
class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // ...
+ }
+}
+
当我们想在当前 Class
中获得泛型 T
或 R
的 Class
实例,只需要如下实现。
示例如下
class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // 获得当前实例的操作对象
+ // 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写
+ val tClass = current().generic()?.argument()
+ // 获得 R 的 Class 实例,在参数第 1 位
+ val rClass = current().generic()?.argument(index = 1)
+ // 你还可以使用如下写法
+ current().generic {
+ // 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写
+ val tClass = argument()
+ // 获得 R 的 Class 实例,在参数第 1 位
+ val rClass = argument(index = 1)
+ }
+ }
+}
+
当我们想在外部调用这个 Class
时,就可以有如下实现。
示例如下
// 假设这个就是 T 的 Class
+class TI {
+
+ fun foo() {
+ // ...
+ }
+}
+// 假设这个就是 T 的实例
+val tInstance: TI? = ...
+// 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写,并获得其中的方法 foo 并调用
+TestGeneric::class.java.generic()?.argument()?.method {
+ name = "foo"
+ emptyParam()
+}?.get(tInstance)?.invoke<TI>()
+
小提示
更多功能请参考 CurrentClass.generic、Class.generic 方法以及 GenericClass。
这里列举了使用时可能会遇到的误区部分,可供参考。
在查找条件中,除了 order
你只能使用一次 index
功能。
示例如下
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ // 错误的使用方法,请仅保留一个 index 方法
+ returnType(StringClass).index(num = 1)
+}
+
以下查找条件的使用是没有任何问题的。
示例如下
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ order().index(num = 1)
+}
+
在普通方法查找条件中,即使是无参的方法也需要设置查找条件。
假设我们有如下的 Class
。
示例如下
public class TestFoo {
+
+ public void foo(String string) {
+ // ...
+ }
+
+ public void foo() {
+ // ...
+ }
+}
+
我们要得到其中的 public void foo()
方法,可以写作如下形式。
示例如下
TestFoo::class.java.method {
+ name = "foo"
+}
+
但是,上面的例子是错误的。
你会发现这个 Class
中有两个 foo
方法,其中一个带有方法参数。
由于上述例子没有设置 param
的查找条件,得到的结果将会是匹配名称且匹配字节码顺序的第一个方法 public void foo(String string)
,而不是我们需要的最后一个方法。
这是一个经常会出现的错误,没有方法参数就会丢失方法参数查找条件的使用问题。
正确的使用方法如下。
示例如下
TestFoo::class.java.method {
+ name = "foo"
+ // ✅ 正确的使用方法,添加详细的筛选条件
+ emptyParam()
+}
+
至此,上述的示例将可以完美地匹配到 public void foo()
方法。
兼容性说明
在过往历史版本的 API 中是允许匹配不写默认匹配无参方法的做法的,但是最新版本更正了这一问题,请确保你使用的是最新的 API 版本。
在构造方法查找条件中,即使是无参的构造方法也需要设置查找条件。
假设我们有如下的 Class
。
示例如下
public class TestFoo {
+
+ public TestFoo() {
+ // ...
+ }
+}
+
我们要得到其中的 public TestFoo()
构造方法,必须写作如下形式。
示例如下
TestFoo::class.java.constructor { emptyParam() }
+
上面的例子可以成功获取到 public TestFoo()
构造方法。
如果你写作 constructor()
而丢失了 emptyParam()
,此时查找到的结果会是按照字节码顺序排列的的第一位,可能并不是无参的。
兼容性说明
在过往历史版本的 API 中构造方法不填写任何查找参数会直接找不到构造方法,这是一个 BUG,最新版本已经进行修复,请确保你使用的是最新的 API 版本。
API 行为变更
在 1.2.0 及之后的版本中,constructor() 的行为不再是 constructor { emptyParam() } 而是 constructor {},请注意行为变更合理调整查找参数。
在不设置查找条件的情况下,使用 field()
、constructor()
、method()
将返回当前 Class
下的所有成员对象。
使用 get(...)
或 give()
的方式获取将只能得到按照字节码顺序排列的的第一位。
示例如下
Test::class.java.field().get(...)
+Test::class.java.method().give()
+
如果你想得到全部成员对象,你可以使用 all(...)
或 giveAll()
示例如下
Test::class.java.field().all(...)
+Test::class.java.method().giveAll()
+
兼容性说明
在过往历史版本的 API 中,不设置查找条件将抛出异常,此特性在 1.2.0 及之后的版本中加入。
在字节码调用结果中,cast 方法只能指定字节码对应的类型。
例如我们想得到一个 Boolean
类型的变量,把他转换为 String
。
以下是错误的使用方法。
示例如下
field {
+ name = "test"
+ type = BooleanType
+}.get().string() // 错误的使用方法,必须 cast 为字节码目标类型
+
以下是正确的使用方法。
示例如下
field {
+ name = "test"
+ type = BooleanType
+}.get().boolean().toString() // ✅ 正确的使用方法,得到类型后再进行转换
+
在查找方法、变量的时候我们通常需要指定所查找的类型。
示例如下
field {
+ name = "test"
+ type = Boolean::class.javaPrimitiveType
+}
+
在 Kotlin 中表达出 Boolean::class.javaPrimitiveType
这个类型的写法很长,感觉并不方便。
因此,YukiReflection
为开发者封装了常见的类型调用,其中包含了 Android 的相关类型和 Java 的常见类型与原始类型关键字。
这个时候上面的类型就可以写作如下形式了。
示例如下
field {
+ name = "test"
+ type = BooleanType
+}
+
在 Java 常见类型中的原始类型 (或基本类型) 关键字都已被封装为 类型 + Type 的方式,例如 IntType
、FloatType
(它们的字节码类型为 int
、float
)。
相应地,数组类型也有方便的使用方法,假设我们要获得 String[]
类型的数组。
需要写做 java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
才能得到这个类型。
感觉是不是很麻烦,这个时候我们可以使用方法 ArrayClass(StringClass)
来得到这个类型。
同时由于 String
是常见类型,所以还可以直接使用 StringArrayClass
来得到这个类型。
一些常见需求中查找的方法,都有其对应的封装类型以供使用,格式为 类型 + Class。
以下是 Java 中一些特例类型在 YukiReflection
中的封装名称。
void
→ UnitType
java.lang.Void
→ UnitClass
java.lang.Object
→ AnyClass
java.lang.Integer
→ IntClass
java.lang.Character
→ CharClass
注意
以 类型 + Type 封装类型会且仅会表示为 Java 原始类型关键字,由于 Kotlin 中不存在原始类型这个概念,所以它们都会被定义为 KClass。
Java 中共有 9 个原始类型关键字,其中 8 个为原始类型,分别为 boolean、char、byte、short、int、float、long、double,其中 void 类型是一个特例。
同时它们都有 Java 自身对应的封装类型,例如 java.lang.Boolean、java.lang.Integer,这些类型是不相等的,请注意区分。
同样地,数组也有对应的封装类型,它们也需要与 Java 原始类型关键字 进行区分。
例如 byte[] 的封装类型为 ByteArrayType 或 ArrayClass(ByteType),而 Byte[] 的封装类型为 ByteArrayClass 或 ArrayClass(ByteClass),这些类型也是不相等的。
同时,欢迎你能贡献更多的常用类型。
`,336);function F(g,k){const p=l("Badge"),o=l("ExternalLinkIcon");return t(),r("div",null,[d,s("h3",A,[y,n(" 模糊查找 "),e(p,{type:"tip",text:"Beta",vertical:"middle"})]),D,s("div",B,[C,u,s("p",null,[n("我们欢迎各位开发者开始使用 "),s("a",v,[n("DexKit"),e(o)]),n(",它是一个使用 C++ 实现的 "),m,n(" 高性能运行时解析库,在性能方面比 Java 层更加高效与优秀,目前尚在开发阶段,欢迎提出宝贵建议。")])]),b])}const q=c(i,[["render",F],["__file","features.html.vue"]]);export{q as default}; diff --git a/assets/future.html-AGWEVq2N.js b/assets/future.html-AGWEVq2N.js new file mode 100644 index 0000000..a82cd39 --- /dev/null +++ b/assets/future.html-AGWEVq2N.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-ae7b83f2","path":"/en/about/future.html","title":"Looking for Future","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Future Plans","slug":"future-plans","link":"#future-plans","children":[{"level":3,"title":"Automatically Generate Reflection Code","slug":"automatically-generate-reflection-code","link":"#automatically-generate-reflection-code","children":[]},{"level":3,"title":"Automatically Generate Directly Called Class Objects","slug":"automatically-generate-directly-called-class-objects","link":"#automatically-generate-directly-called-class-objects","children":[]}]}],"git":{"updatedTime":1702855553000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"en/about/future.md"}');export{e as data}; diff --git a/assets/future.html-ejs_q7b1.js b/assets/future.html-ejs_q7b1.js new file mode 100644 index 0000000..3d89492 --- /dev/null +++ b/assets/future.html-ejs_q7b1.js @@ -0,0 +1,102 @@ +import{_ as s,o as n,c as a,a as l}from"./app-Un_zyw_U.js";const e={},o=l(`The future is bright and uncertain, let us look forward to the future development space of
YukiReflection
.
Features that
YukiReflection
may add later are included here.
Use stub
to create a Kotlin class, and declare the parameters in it, as well as its different states in each version.
For example, the Java class below is the target class we need to reflect.
The following example
package com.example.test;
+
+public class MyClass {
+
+ private String myField = "test";
+
+ public MyClass() {
+ //...
+ }
+
+ private String myMethod1(String var1, int var2) {
+ //...
+ }
+
+ private void myMethod2() {
+ //...
+ }
+
+ private void myMethod3(String var1) {
+ //...
+ }
+}
+
Through the existing usage of the current API, this class can be called reflectively in the following way.
The following example
classOf<MyClass>().buildOf().current {
+ // Call myField
+ val value = field { name = "myField" }.string()
+ // Call myMethod1
+ val methodValue = method { name = "myMethod1" }.string("test", 0)
+ // Call myMethod2
+ method { name = "myMethod2" }.call()
+ // Call myMethod3
+ method { name = "myMethod3" }.call("test")
+}
+
The function to be implemented at present can be directly defined as the following Kotlin class using the reflection function.
The following example
package com.example.test
+
+@ReflectClass
+class MyClass {
+
+ @ReflectField
+ val myField: String = fieldValueOf("none")
+
+ @ReflectMethod
+ fun myMethod1(var1: String, var2: Int): String = methodReturnValueOf("none")
+
+ @ReflectMethod
+ fun myMethod2() = MethodReturnType.Unit
+
+ @ReflectMethod
+ fun myMethod3(var1: String) = MethodReturnType.Unit
+}
+
Then we can directly call this defined Kotlin class to implement the reflection function, and the API will automatically generate the reflection code according to the annotation.
The following example
MyClass().also {
+ // Call myField
+ val value = it.myField
+ // Call myMethod1
+ val methodValue = it.myMethod1("test", 0)
+ // Call myMethod2
+ it.myMethod2()
+ // Call myMethod3
+ it.myMethod3("test")
+}
+
Tips
The above functions may change after the actual release, and the functions of the actual version shall prevail.
In Kotlin, the way to represent Java class objects is YourObject::class.java
.
This writing method is usually very long and will be very unsightly when used extensively during reflection.
In the existing version, we have built-in commonly used Class
objects, but this will increase the size of dependencies, and these objects may not be used in most cases.
For example, StringClass
, IntType
, etc., these objects are built in YukiReflection
.
So we plan to add a function in the future, which can use properties
to create a list of Class
objects that need to be generated, and generate these Class
objects in sequence through the Gradle plugin.
Class
objects of primitive types such as those mentioned above will still be built into YukiReflection
, and the remaining Class
objects need to be defined by yourself.
The generated name specification is Class Name + Class.
In order to prevent package name conflicts, you can control the sub-package name of the generated Class
object.
In the configuration file, you don't need to add Class
as a suffix.
You can define the generated root package name in the Gradle plugin, which defaults to com.highcapable.yukireflection.generated.classes
.
The following example
# The most basic way to define is to write the name directly
+# Will be generated to com.highcapable.yukireflection.generated.classes.BundleClass
+android.os.Bundle=Bundle
+# You can use the "." form in front to define the prefixed subpackage name
+# For example, we want to define this class to the desired package name
+# Will be generated to com.highcapable.yukireflection.generated.classes.myandroid.myos.BundleClass
+android.os.Bundle=myandroid.myos.Bundle
+# You can also not fill in the key value content, which will use the key value name
+# as the defined package name and class name
+# Will be generated to com.highcapable.yukireflection.generated.classes.android.os.BundleClass
+android.os.Bundle
+
The approximate code form of the Class
object generated by the above method is as follows.
package com.highcapable.yukireflection.generated.classes.android.os
+
+// Used with default ClassLoader
+val BundleClass: Class<*> = "android.os.Bundle".toClass()
+
+// Used when ClassLoader is specified
+fun BundleClass(loader: ClassLoader): Class<*> = "android.os.Bundle".toClass(loader)
+
Maybe this Class
may not be obtained in some cases.
In this case, you can refer to the following configuration method.
The following example
# Add "?" after the key value to define a nullable Class object
+android.os.Bundle?
+
The approximate code form of the Class
object generated by the above method is as follows.
package com.highcapable.yukireflection.generated.classes.android.os
+
+// Used with default ClassLoader
+val BundleClass: Class<*>? = "android.os.Bundle".toClassOrNull()
+
+// Used when ClassLoader is specified
+fun BundleClass(loader: ClassLoader): Class<*>? = "android.os.Bundle".toClassOrNull(loader)
+
If this Class
object can be referenced by direct call, you can refer to the following configuration method at this time.
The following example
# Add "!!" after the key value to define a Class object that can be called directly
+android.os.Bundle!!
+
The approximate code form of the Class
object generated by the above method is as follows.
package com.highcapable.yukireflection.generated.classes.android.os
+
+import android.os.Bundle
+
+// Used with default ClassLoader
+val BundleClass: Class<Bundle> = classOf<Bundle>()
+
+// Used when ClassLoader is specified
+fun BundleClass(loader: ClassLoader): Class<Bundle> = classOf<Bundle>(loader)
+
With the generated Class
object, we can happily use YukiReflection
for reflection.
The following example
method {
+ name = "onCreate"
+ param(BundleClass)
+}
+
Tips
The above functions may change after the actual release, and the functions of the actual version shall prevail.
未来是美好的,也是不确定的,让我们共同期待
YukiReflection
在未来的发展空间。
这里收录了
YukiReflection
可能会在后期添加的功能。
使用 stub
的方式创建一个 Kotlin 类,并声明其中的参数,以及其在各个版本中的不同状态。
比如下面的这个 Java 类就是我们需要反射的目标类。
示例如下
package com.example.test;
+
+public class MyClass {
+
+ private String myField = "test";
+
+ public MyClass() {
+ // ...
+ }
+
+ private String myMethod1(String var1, int var2) {
+ // ...
+ }
+
+ private void myMethod2() {
+ // ...
+ }
+
+ private void myMethod3(String var1) {
+ // ...
+ }
+}
+
通过目前 API 的现有用法可以使用如下方式反射调用这个类。
示例如下
classOf<MyClass>().buildOf().current {
+ // 调用 myField
+ val value = field { name = "myField" }.string()
+ // 调用 myMethod1
+ val methodValue = method { name = "myMethod1" }.string("test", 0)
+ // 调用 myMethod2
+ method { name = "myMethod2" }.call()
+ // 调用 myMethod3
+ method { name = "myMethod3" }.call("test")
+}
+
目前要实现的功能是可以使用反射功能直接定义为如下 Kotlin 类。
示例如下
package com.example.test
+
+@ReflectClass
+class MyClass {
+
+ @ReflectField
+ val myField: String = fieldValueOf("none")
+
+ @ReflectMethod
+ fun myMethod1(var1: String, var2: Int): String = methodReturnValueOf("none")
+
+ @ReflectMethod
+ fun myMethod2() = MethodReturnType.Unit
+
+ @ReflectMethod
+ fun myMethod3(var1: String) = MethodReturnType.Unit
+}
+
然后我们就可以直接调用这个定义好的 Kotlin 类来实现反射功能,API 会根据注解自动生成反射代码。
示例如下
MyClass().also {
+ // 调用 myField
+ val value = it.myField
+ // 调用 myMethod1
+ val methodValue = it.myMethod1("test", 0)
+ // 调用 myMethod2
+ it.myMethod2()
+ // 调用 myMethod3
+ it.myMethod3("test")
+}
+
小提示
以上功能可能会在实际推出后有所变化,最终以实际版本的功能为准。
在 Kotlin 中,表示 Java 的类对象的方式是 YourObject::class.java
,这个写法通常会很长,在反射过程中大量使用会很不美观。
在现有版本中,我们内置了常用的 Class
对象,但是这会增大依赖的体积,而且大多数情况下可能都用不到这些对象。
例如 StringClass
、IntType
等等,这些对象都是在 YukiReflection
中内置的。
所以我们计划在后期添加一个功能,可以使用 properties
的方式创建一个需要生成的 Class
对象列表,通过 Gradle 插件依次生成这些 Class
对象。
诸如上面提到的这些原始类型的 Class
对象依然会内置在 YukiReflection
中,其余的 Class
对象需要自行定义。
生成的名称规范为 类名 + Class,为了防止包名冲突,你可以控制生成的 Class
对象的子包名。
在配置文件中,你无需添加 Class
作为后缀。
你可以在 Gradle 插件中定义生成的根包名,默认为 com.highcapable.yukireflection.generated.classes
。
示例如下
# 最基本的定义方式就是直接写名称
+# 将会生成到 com.highcapable.yukireflection.generated.classes.BundleClass
+android.os.Bundle=Bundle
+# 你可以在前方使用 "." 的形式来定义前置子包名
+# 例如我们想把这个类定义到想要的包名
+# 将会生成到 com.highcapable.yukireflection.generated.classes.myandroid.myos.BundleClass
+android.os.Bundle=myandroid.myos.Bundle
+# 你也可以不填写键值内容,这将使用键值名称作为定义的包名和类名
+# 将会生成到 com.highcapable.yukireflection.generated.classes.android.os.BundleClass
+android.os.Bundle
+
上述方式生成的 Class
对象的大概代码形式如下。
package com.highcapable.yukireflection.generated.classes.android.os
+
+// 在默认 ClassLoader 的情况下使用
+val BundleClass: Class<*> = "android.os.Bundle".toClass()
+
+// 在指定 ClassLoader 的情况下使用
+fun BundleClass(loader: ClassLoader): Class<*> = "android.os.Bundle".toClass(loader)
+
也许这个 Class
可能在一些情况下无法被得到,这个时候你可以参考以下配置方式。
示例如下
# 在键值后添加 "?" 的形式来定义可空的 Class 对象
+android.os.Bundle?
+
上述方式生成的 Class
对象的大概代码形式如下。
package com.highcapable.yukireflection.generated.classes.android.os
+
+// 在默认 ClassLoader 的情况下使用
+val BundleClass: Class<*>? = "android.os.Bundle".toClassOrNull()
+
+// 在指定 ClassLoader 的情况下使用
+fun BundleClass(loader: ClassLoader): Class<*>? = "android.os.Bundle".toClassOrNull(loader)
+
如果这个 Class
对象能使用直接调用的方式进行引用,这个时候你可以参考以下配置方式。
示例如下
# 在键值后添加 "!!" 的形式来定义可直接调用的 Class 对象
+android.os.Bundle!!
+
上述方式生成的 Class
对象的大概代码形式如下。
package com.highcapable.yukireflection.generated.classes.android.os
+
+import android.os.Bundle
+
+// 在默认 ClassLoader 的情况下使用
+val BundleClass: Class<Bundle> = classOf<Bundle>()
+
+// 在指定 ClassLoader 的情况下使用
+fun BundleClass(loader: ClassLoader): Class<Bundle> = classOf<Bundle>(loader)
+
有了生成的 Class
对象,我们就可以愉快地使用 YukiReflection
进行反射了。
示例如下
method {
+ name = "onCreate"
+ param(BundleClass)
+}
+
小提示
以上功能可能会在实际推出后有所变化,最终以实际版本的功能为准。
The document here will synchronize the relevant usage of the latest API version, please keep
YukiReflection
as the latest version to use the latest version of the function.
The function description mainly introduces the related usage and purpose of the current API.
The function examples mainly show the basic usage examples of the current API for reference.
The function of the first version will be marked as v<version>
first
;
New function added later will be marked as v<version>
added
;
Later modified function will be appended as v<version>
modified
;
Later deprecated function will be marked as v<version>
deprecated
and strikethrough;
Later removed function will be marked as v<version>
removed
and strikethrough.
kt Kotlin Static File
annotation Annotation Class
interface Interface Class
object Class (Singleton)
class Class
field Field or get
/ set
method or read-only get
method
method Method
enum Enum constant
ext-field Extension field (global)
ext-method Extension method (global)
i-ext-field Extension field (internal)
i-ext-method Extension method (internal)
这里的文档将同步最新 API 版本的相关用法,请保持
YukiReflection
为最新版本以使用最新版本的功能。
功能描述主要介绍当前 API 的相关用法和用途。
功能示例主要展示了当前 API 的基本用法示例,可供参考。
首个版本的功能将标记为 v<version>
添加
;
后期新增加的功能将标记为 v<version>
新增
;
后期修改的功能将被追加为 v<version>
修改
;
后期被作废的功能将标记为 v<version>
作废
并会标注删除线;
后期被删除的功能将标记为 v<version>
移除
并会标注删除线。
kt Kotlin Static File
annotation 注解
interface 接口
object 类 (单例)
class 类
field 变量或 get
、set
方法或只读的 get
方法
method 方法
enum Enum 常量
ext-field 扩展的变量 (全局)
ext-method 扩展的方法 (全局)
i-ext-field 扩展的变量 (调用域限制)
i-ext-method 扩展的方法 (调用域限制)
public class World {
+
+ private void sayHello(String content) {
+ System.out.println("Hello " + content + "!");
+ }
+}
+
val newWorld = World()
+classOf<World>().method {
+ name = "sayHello"
+ param(StringClass)
+ type = UnitType
+}.get(newWorld).call("YukiReflection")
+
public class World {
+
+ private void sayHello(String content) {
+ System.out.println("Hello " + content + "!");
+ }
+}
+
val newWorld = World()
+classOf<World>().method {
+ name = "sayHello"
+ param(StringClass)
+ type = UnitType
+}.get(newWorld).call("YukiReflection")
+
集成
YukiReflection
到你的项目中。
Windows 7 及以上/macOS 10.14 及以上/Linux 发行版 (Arch/Debian)
Android Studio 2021.1 及以上
IntelliJ IDEA 2021.1 及以上
Kotlin 1.7.0 及以上
Android Gradle Plugin 7.0 及以上
Gradle 7.0 及以上
Java 11 及以上
Java 17 及以上 (Since API 1.0.3
)
项目需要使用 Android Studio
或 IntelliJ IDEA
创建且类型为 Java 或 Android 项目并已集成 Kotlin 环境依赖。
在你的项目 SweetDependency
配置文件中添加存储库和依赖。
示例如下
repositories:
+ # MavenCentral 有 2 小时缓存,若无法集成最新版本请添加
+ sonatype-oss-releases:
+
+libraries:
+ com.highcapable.yukireflection:
+ api:
+ version: +
+ ...
+
添加完成后运行一次 Gradle Sync,所有依赖版本将自动装配。
接下来,在你的项目 build.gradle.kts
中部署依赖。
示例如下
dependencies {
+ implementation(com.highcapable.yukireflection.api)
+ // ...
+}
+
在你的项目 build.gradle.kts
或 build.gradle
中添加存储库。
Kotlin DSL
repositories {
+ google()
+ mavenCentral()
+ // MavenCentral 有 2 小时缓存,若无法集成最新版本请添加此地址
+ maven { url("https://s01.oss.sonatype.org/content/repositories/releases/") }
+}
+
Groovy DSL
repositories {
+ google()
+ mavenCentral()
+ // MavenCentral 有 2 小时缓存,若无法集成最新版本请添加此地址
+ maven { url 'https://s01.oss.sonatype.org/content/repositories/releases/' }
+}
+
在你的项目 build.gradle.kts
或 build.gradle
中添加依赖。
Kotlin DSL
dependencies {
+ implementation("com.highcapable.yukireflection:api:<yuki-version>")
+ // ...
+}
+
Groovy DSL
dependencies {
+ implementation 'com.highcapable.yukireflection:api:<yuki-version>'
+ // ...
+}
+
请将 <yuki-version> 修改为 这里 的最新版本。
`,20),v={class:"custom-container danger"},A=n("p",{class:"custom-container-title"},"特别注意",-1),y={href:"https://github.com/HighCapable/YukiHookAPI",target:"_blank",rel:"noopener noreferrer"},b=n("strong",null,"YukiReflection",-1),m=n("strong",null,"YukiHookAPI",-1),D=n("strong",null,"YukiHookAPI",-1),h={href:"https://highcapable.github.io/YukiHookAPI/zh-cn/",target:"_blank",rel:"noopener noreferrer"},B=n("p",null,[n("strong",null,"YukiHookAPI"),s(" 将在 "),n("strong",null,"2.0.0"),s(" 版本完全分离 "),n("strong",null,"YukiReflection"),s(",届时你可以同时与 "),n("strong",null,"YukiHookAPI"),s(" 使用。")],-1),C=l(`在你的项目 build.gradle.kts
或 build.gradle
中修改 Kotlin 的 Java 版本为 17 及以上。
Kotlin DSL
android {
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+}
+
Groovy DSL
android {
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = '17'
+ }
+}
+
注意
自 API 1.0.3 版本后 Kotlin 使用的 Java 版本默认为 17,不再支持 11 及以下版本。
Integrate
YukiReflection
into your project.
Windows 7 and above / macOS 10.14 and above / Linux distributions (Arch/Debian)
Android Studio 2021.1 and above
IntelliJ IDEA 2021.1 and above
Kotlin 1.7.0 and above
Android Gradle Plugin 7.0 and above
Gradle 7.0 and above
Java 11 and above
Java 17 and above (Since API 1.0.3
)
The project needs to be created using Android Studio
or IntelliJ IDEA
and the type is an Java or Android project and the Kotlin environment dependency has been integrated.
Add the repositories and dependencies in your project's SweetDependency
configuration file.
The following example
repositories:
+ # MavenCentral has a 2-hour cache,
+ # if the latest version cannot be integrated, please add this
+ sonatype-oss-releases:
+
+libraries:
+ com.highcapable.yukireflection:
+ api:
+ version: +
+ ...
+
After adding it, run Gradle Sync and all dependencies will be autowired.
Next, deploy dependencies in your project build.gradle.kts
.
The following example
dependencies {
+ implementation(com.highcapable.yukireflection.api)
+ // ...
+}
+
Add repositories in your project build.gradle.kts
or build.gradle
.
Kotlin DSL
repositories {
+ google()
+ mavenCentral()
+ // MavenCentral has a 2-hour cache, if the latest version cannot be integrated, please add this URL
+ maven { url("https://s01.oss.sonatype.org/content/repositories/releases/") }
+}
+
Groovy DSL
repositories {
+ google()
+ mavenCentral()
+ // MavenCentral has a 2-hour cache, if the latest version cannot be integrated, please add this URL
+ maven { url 'https://s01.oss.sonatype.org/content/repositories/releases/' }
+}
+
Add dependencies in your project build.gradle.kts
or build.gradle
.
Kotlin DSL
dependencies {
+ implementation("com.highcapable.yukireflection:api:<yuki-version>")
+ // ...
+}
+
Groovy DSL
dependencies {
+ implementation 'com.highcapable.yukireflection:api:<yuki-version>'
+ // ...
+}
+
Please change <yuki-version> to the latest version here.
`,20),v={class:"custom-container danger"},y=s("p",{class:"custom-container-title"},"Pay Attention",-1),b={href:"https://github.com/HighCapable/YukiHookAPI",target:"_blank",rel:"noopener noreferrer"},A=s("strong",null,"YukiReflection",-1),m=s("strong",null,"YukiHookAPI",-1),h=s("p",null,"Repeated integration will cause functional conflicts and cause exceptions.",-1),D={href:"https://highcapable.github.io/YukiHookAPI/zh-cn/",target:"_blank",rel:"noopener noreferrer"},g=s("strong",null,"YukiHookAPI",-1),B=s("p",null,[s("strong",null,"YukiHookAPI"),n(" will be completely separated from "),s("strong",null,"YukiReflection"),n(" in version "),s("strong",null,"2.0.0"),n(", by which time you can use it with "),s("strong",null,"YukiHookAPI"),n(" at the same time.")],-1),C=l(`Modify the Java version of Kotlin in your project build.gradle.kts
or build.gradle
to 17 or above.
Kotlin DSL
android {
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+}
+
Groovy DSL
android {
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = '17'
+ }
+}
+
Notice
Since API 1.0.3, the Java version used by Kotlin defaults to 17, and versions 11 and below are no longer supported.
This document is powered by VuePress.
Apache License Version 2.0
+
+Copyright (C) 2019 HighCapable
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
Copyright © 2019 HighCapable
The version update history of
YukiReflection
is recorded here.
Pay Attention
We will only maintain the latest API version, if you are using an outdate API version, you voluntarily renounce any possibility of maintenance.
Notice
To avoid translation time consumption, Changelog will use Google Translation from Chinese to English, please refer to the original text for actual reference.
Time zone of version release date: UTC+8
MIT
to Apache-2.0
, subsequent versions will be distributed under this license agreement, you should change the relevant license agreement after using this versionYukiReflection
isAllowPrintingLogs
debugLog
methodYukiReflection.TAG
YukiReflection.API_VERSION_NAME
YukiReflection.API_VERSION_CODE
YukiReflection.VERSION
remendy
functionality in find methods, which now prints exceptions in stepsHashSet
to MutableList
method()
, constructor()
, field()
to directly obtain all object functions in the classconstructor()
no longer behaves like constructor { emptyParam() }
lazyClass
and lazyClassOrNull
methods to lazily load Class
Member
cache did not take effect and persistent storage eventually caused app out of memory (OOM), thanks to Art-ChenMember
and deprecated YukiReflection.Configs.isEnableMemberCache
Class
Sequence
, optimize the finding speed and performance of Member
Class
object declaration in Android type
If you have any questions in use, or have any constructive suggestions, you can contact us.
Join our developers group.
Find me on Twitter @fankesyooni.
Thank you for choosing and using YukiReflection
.
If you have code-related suggestions and requests, you can submit a Pull Request on GitHub.
The future is bright and uncertain, let us look forward to the future development space of
YukiReflection
.
Features that
YukiReflection
may add later are included here.
Use stub
to create a Kotlin class, and declare the parameters in it, as well as its different states in each version.
For example, the Java class below is the target class we need to reflect.
The following example
package com.example.test;
+
+public class MyClass {
+
+ private String myField = "test";
+
+ public MyClass() {
+ //...
+ }
+
+ private String myMethod1(String var1, int var2) {
+ //...
+ }
+
+ private void myMethod2() {
+ //...
+ }
+
+ private void myMethod3(String var1) {
+ //...
+ }
+}
+
Through the existing usage of the current API, this class can be called reflectively in the following way.
The following example
classOf<MyClass>().buildOf().current {
+ // Call myField
+ val value = field { name = "myField" }.string()
+ // Call myMethod1
+ val methodValue = method { name = "myMethod1" }.string("test", 0)
+ // Call myMethod2
+ method { name = "myMethod2" }.call()
+ // Call myMethod3
+ method { name = "myMethod3" }.call("test")
+}
+
The function to be implemented at present can be directly defined as the following Kotlin class using the reflection function.
The following example
package com.example.test
+
+@ReflectClass
+class MyClass {
+
+ @ReflectField
+ val myField: String = fieldValueOf("none")
+
+ @ReflectMethod
+ fun myMethod1(var1: String, var2: Int): String = methodReturnValueOf("none")
+
+ @ReflectMethod
+ fun myMethod2() = MethodReturnType.Unit
+
+ @ReflectMethod
+ fun myMethod3(var1: String) = MethodReturnType.Unit
+}
+
Then we can directly call this defined Kotlin class to implement the reflection function, and the API will automatically generate the reflection code according to the annotation.
The following example
MyClass().also {
+ // Call myField
+ val value = it.myField
+ // Call myMethod1
+ val methodValue = it.myMethod1("test", 0)
+ // Call myMethod2
+ it.myMethod2()
+ // Call myMethod3
+ it.myMethod3("test")
+}
+
Tips
The above functions may change after the actual release, and the functions of the actual version shall prevail.
In Kotlin, the way to represent Java class objects is YourObject::class.java
.
This writing method is usually very long and will be very unsightly when used extensively during reflection.
In the existing version, we have built-in commonly used Class
objects, but this will increase the size of dependencies, and these objects may not be used in most cases.
For example, StringClass
, IntType
, etc., these objects are built in YukiReflection
.
So we plan to add a function in the future, which can use properties
to create a list of Class
objects that need to be generated, and generate these Class
objects in sequence through the Gradle plugin.
Class
objects of primitive types such as those mentioned above will still be built into YukiReflection
, and the remaining Class
objects need to be defined by yourself.
The generated name specification is Class Name + Class.
In order to prevent package name conflicts, you can control the sub-package name of the generated Class
object.
In the configuration file, you don't need to add Class
as a suffix.
You can define the generated root package name in the Gradle plugin, which defaults to com.highcapable.yukireflection.generated.classes
.
The following example
# The most basic way to define is to write the name directly
+# Will be generated to com.highcapable.yukireflection.generated.classes.BundleClass
+android.os.Bundle=Bundle
+# You can use the "." form in front to define the prefixed subpackage name
+# For example, we want to define this class to the desired package name
+# Will be generated to com.highcapable.yukireflection.generated.classes.myandroid.myos.BundleClass
+android.os.Bundle=myandroid.myos.Bundle
+# You can also not fill in the key value content, which will use the key value name
+# as the defined package name and class name
+# Will be generated to com.highcapable.yukireflection.generated.classes.android.os.BundleClass
+android.os.Bundle
+
The approximate code form of the Class
object generated by the above method is as follows.
package com.highcapable.yukireflection.generated.classes.android.os
+
+// Used with default ClassLoader
+val BundleClass: Class<*> = "android.os.Bundle".toClass()
+
+// Used when ClassLoader is specified
+fun BundleClass(loader: ClassLoader): Class<*> = "android.os.Bundle".toClass(loader)
+
Maybe this Class
may not be obtained in some cases.
In this case, you can refer to the following configuration method.
The following example
# Add "?" after the key value to define a nullable Class object
+android.os.Bundle?
+
The approximate code form of the Class
object generated by the above method is as follows.
package com.highcapable.yukireflection.generated.classes.android.os
+
+// Used with default ClassLoader
+val BundleClass: Class<*>? = "android.os.Bundle".toClassOrNull()
+
+// Used when ClassLoader is specified
+fun BundleClass(loader: ClassLoader): Class<*>? = "android.os.Bundle".toClassOrNull(loader)
+
If this Class
object can be referenced by direct call, you can refer to the following configuration method at this time.
The following example
# Add "!!" after the key value to define a Class object that can be called directly
+android.os.Bundle!!
+
The approximate code form of the Class
object generated by the above method is as follows.
package com.highcapable.yukireflection.generated.classes.android.os
+
+import android.os.Bundle
+
+// Used with default ClassLoader
+val BundleClass: Class<Bundle> = classOf<Bundle>()
+
+// Used when ClassLoader is specified
+fun BundleClass(loader: ClassLoader): Class<Bundle> = classOf<Bundle>(loader)
+
With the generated Class
object, we can happily use YukiReflection
for reflection.
The following example
method {
+ name = "onCreate"
+ param(BundleClass)
+}
+
Tips
The above functions may change after the actual release, and the functions of the actual version shall prevail.
This page contains usage examples for all core features of
YukiReflection
.
Here are the extension functions related to the Class object itself.
Suppose we want to get a Class
that cannot be called directly.
Normally, we can use the standard reflection API to find this Class
.
The following example
// Class in the default ClassLoader environment
+var instance = Class.forName("com.demo.Test")
+// Specify the Class in the ClassLoader environment
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = customClassLoader?.loadClass("com.demo.Test")
+
This is probably not very friendly, and YukiReflection
provides you with a syntactic sugar that can be used anywhere.
The above writing can be written as YukiReflection
as follows.
The following example
// Get this Class directly
+var instance = "com.demo.Test".toClass()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = "com.demo.Test".toClass(customClassLoader)
+
If the current Class
does not exist, using the above method will throw an exception.
If you are not sure whether the Class
exists, you can refer to the following solutions.
The following example
// Get this Class directly
+// If not available, the result will be null but no exception will be thrown
+var instance = "com.demo.Test".toClassOrNull()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+// If not available, the result will be null but no exception will be thrown
+var instance = "com.demo.Test".toClassOrNull(customClassLoader)
+
We can also get an existing Class
object by mapping.
The following example
// Assume this Class can be obtained directly
+var instance = classOf<Test>()
+// We can also customize the ClassLoader where the Class is located, which is very effective for stubs
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = classOf<Test>(customClassLoader)
+
Tips
For more functions, please refer to classOf, String.toClass, String.toClassOrNull methods.
Suppose we want to get a Class
that cannot be called directly, but we do not need this Class
immediately.
At this time, you can use lazyClass
to complete this function.
The following example
// Lazy loading of this Class
+val instance by lazyClass("com.demo.Test")
+// Customize the ClassLoader where the Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+val instance by lazyClass("com.demo.Test") { customClassLoader }
+// Call this Class at the appropriate time
+instance.method {
+ // ...
+}
+
If the current Class
does not exist, using the above method will throw an exception.
If you are not sure whether Class
exists, you can refer to the following solution.
The following example
// Lazy loading of this Class
+// If not available, the result will be null but no exception will be thrown
+val instance by lazyClassOrNull("com.demo.Test")
+// Customize the ClassLoader where the Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+// If not available, the result will be null but no exception will be thrown
+val instance by lazyClassOrNull("com.demo.Test") { customClassLoader }
+// Call this Class at the appropriate time
+instance?.method {
+ // ...
+}
+
Tips
For more functions, please refer to lazyClass, lazyClassOrNull methods.
Suppose we want to determine whether a Class
exists.
Usually, we can use the standard reflection API to find this Class
to determine whether it exists by exception.
The following example
// Class in the default ClassLoader environment
+var isExist = try {
+ Class.forName("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+// Specify the Class in the ClassLoader environment
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var isExist = try {
+ customClassLoader?.loadClass("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+
This is probably not very friendly, and YukiReflection
provides you with a syntactic sugar that can be used anywhere.
The above writing can be written as YukiReflection
as follows.
The following example
// Check if this class exists
+var isExist = "com.demo.Test".hasClass()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var isExist = "com.demo.Test".hasClass(customClassLoader)
+
Tips
For more functions, please refer to String.hasClass method.
The Class
name in the current app's Dex after being obfuscated by tools such as R8 will be difficult to distinguish.
Its correct position is uncertain, and cannot be obtained directly through Object Conversion.
At this point, there is DexClassFinder
, its role is to determine the instance of this Class
by the bytecode features in the Class
that need to be searched.
Notice
This feature is only available on the Android platform.
At present, the function of DexClassFinder is still in the experimental stage.
Since the search function is only implemented through the Java layer, the performance may not reach the optimal level when there are too many current app's Class.
If something got wrong welcome to feedback.
Since it is a reflection-level API, currently it can only locate the specified Class through the characteristics of Class and Member, and cannot locate it by specifying the string and method content characteristics in the bytecode.
The speed of searching Class depends on the performance of the current device.
At present, the mainstream mobile processors are in the 3~10s range when the conditions are not complicated in the 10~15w number of Class, the fastest speed can reach within 25s under slightly complex conditions.
Please note that the more the same type Class is matched, the slower the speed.
Pay Attention
After YukiHookAPI 2.0.0 released, this function will be deprecated and will be removed directly from YukiReflection.
We welcome all developers to start using DexKit, which is a high-performance runtime parsing library for Dex implemented in C++, which is more efficient than the Java layer in terms of performance, efficient and excellent, it is still in the development stage, your valuable suggestions are welcome.
Below is a simple usage example.
Suppose the following Class
is what we want, the names are obfuscated and may be different in each version.
The following example
package com.demo;
+
+public class a extends Activity implements Serializable {
+
+ public a(String var1) {
+ // ...
+ }
+
+ private String a;
+
+ private String b;
+
+ private boolean a;
+
+ protected void onCreate(Bundle var1) {
+ // ...
+ }
+
+ private static void a(String var1) {
+ // ...
+ }
+
+ private String a(boolean var1, String var2) {
+ // ...
+ }
+
+ private void a() {
+ // ...
+ }
+
+ public void a(boolean var1, a var2, b var3, String var4) {
+ // ...
+ }
+}
+
At this point, we want to get this Class
, you can use the ClassLoader.searchClass
method directly.
Each of the conditions demonstrated below is optional, and the more complex the conditions, the more accurate the positioning and the worse the performance.
The following example
searchClass {
+ // Start the search from the specified package name range
+ // In actual use, you can specify multiple package name ranges at the same time
+ from("com.demo")
+ // Specify the result of getSimpleName of the current Class
+ // You can directly make logical judgments on this string
+ // Here we are not sure whether its name is a, we can only judge the length of the string
+ simpleName { it.length == 1 }
+ // Specify the inherited parent class object
+ // If it is an existing stub, it can be directly represented by generics
+ extends<Activity>()
+ // Specify the inherited parent class object
+ // Which can be written directly as the full class name
+ // And you can also specify multiple objects at the same time
+ extends("android.app.Activity")
+ // Specify the implemented interface
+ // If it exists stub, can be directly represented by generics
+ implements<Serializable>()
+ // Specify the implemented interface
+ // Which can be written directly as a full class name, or you can specify multiple at the same time
+ implements("java.io.Serializable")
+ // Specify the type and style of the constructor
+ // And the number count that exists in the current class
+ constructor { param(StringClass) }.count(num = 1)
+ // Specify the type and style of the variable
+ // And the number that exists in the current class count
+ field { type = StringClass }.count(num = 2)
+ // Specify the type and style of the variable
+ // And the number that exists in the current class count
+ field { type = BooleanType }.count(num = 1)
+ // Directly specify the number of all variables that exist in the current class count
+ field().count(num = 3)
+ // If you think the number of variables is indeterminate
+ // You can also use the following custom conditions
+ field().count(1..3)
+ field().count { it >= 3 }
+ // Specify the type and style of the method
+ // And the number that exists in the current class count
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // Specify the modifier, and the number count in the current class
+ method {
+ modifiers { isStatic && isPrivate }
+ param(StringClass)
+ returnType = UnitType
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // Specify the modifier, and the number count in the current class
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, StringClass)
+ returnType = StringClass
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // Specify the modifier, and the number count in the current class
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ emptyParam()
+ returnType = UnitType
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // As well as the modifier and VagueType
+ // And the number count that exists in the current class
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, VagueType, VagueType, StringClass)
+ returnType = UnitType
+ }.count(num = 1)
+ // Directly specify the number of all methods that exist in the current class count
+ method().count(num = 5)
+ // If you think the number of methods is uncertain, you can also use the following custom conditions
+ method().count(1..5)
+ method().count { it >= 5 }
+ // Directly specify the number of all members existing in the current class count
+ // Members include: Field, Method, Constructor
+ member().count(num = 9)
+ // There must be a static modifier in all members, you can add this condition like this
+ member {
+ modifiers { isStatic }
+ }
+}.get() // Get the instance of this Class itself, if not found, it will return null
+
Tips
The conditional usage of Field, Method, Constructor in the above usage is consistent with the related usage in Member Extensions, with only minor differences.
For more functions, please refer to MemberRules, FieldRules, MethodRules, ConstructorRules.
By default, DexClassFinder
will use synchronous mode to search Class
, which will block the current thread until it finds or finds an exception.
If the search takes too long, it may cause ANR problems to the current app.
In response to the above problems, we can enable asynchronous, just add the parameter async = true
, which will not require you to start a thread again, the API has already handled the related problems for you.
Notice
To use this function, you need to pass in the Context of the current app as the first method parameter.
For the asynchronous case you need to use the wait method to get the result, the get method will no longer work.
The following example
val context: Context // Assume this is the Context of the current app
+searchClass(context, async = true) {
+ // ...
+}.wait { class1 ->
+ // Get asynchronous result
+}
+searchClass(context, async = true) {
+ // ...
+}.wait { class2 ->
+ // Get asynchronous result
+}
+
In this way, our search process runs asynchronously, it will not block the main thread, and each search will be performed in a separate thread at the same time, which can achieve the effect of parallel tasks.
Since the search is performed again every time the current app is reopened, this is a waste of repetitive performance when the current app's version is unchanged.
At this point, we can locally cache the search results of the current app's version by specifying the name
parameter.
Next time, the found class name will be directly read from the local cache.
The local cache uses SharedPreferences
, which will be saved to the app's data directory and will be re-cached after the app's version is updated.
After enabling the local cache, async = true
will be set at the same time, you don't need to set it manually.
Notice
To use this function, you need to pass in the Context of the current app as the first method parameter.
The following example
val context: Context // Assume this is the Context of the current app
+searchClass(context, name = "com.demo.class1") {
+ // ...
+}.wait { class1 ->
+ // Get asynchronous result
+}
+searchClass(context, name = "com.demo.class2") {
+ // ...
+}.wait { class2 ->
+ // Get asynchronous result
+}
+
If you want to clear the local cache manually, you can use the following method to clear the current version of the current app's cache.
The following example
val context: Context // Assume this is the Context of the current app
+DexClassFinder.clearCache(context)
+
You can also clear the app's cache for a specific version.
The following example
val context: Context // Assume this is the Context of the current app
+DexClassFinder.clearCache(context, versionName = "1.0", versionCode = 1)
+
If you need to search a set of Class
at the same time using a fixed condition, then you only need to use the all
or waitAll
method to get the result.
// Synchronous search, use all to get all the results found by the conditions
+searchClass {
+ // ...
+}.all().forEach { clazz ->
+ // Get each result
+}
+// Synchronous search, using all { ... } to iterate over each result
+searchClass {
+ // ...
+}.all { clazz ->
+ // Get each result
+}
+// Asynchronous search, use waitAll to get all the results found by the conditions
+val context: Context // Assume this is the Context of the current app
+searchClass(context, async = true) {
+ // ...
+}.waitAll { classes ->
+ classes.forEach {
+ // Get each result
+ }
+}
+
Tips
For more functions, please refer to ClassLoader.searchClass method.
Here are the extension functions related to the Class bytecode member variables Field, Method, Constructor.
Tips
Member is the interface description object of Field, Method, Constructor, which is the general term for the bytecode members in Class in Java reflection.
Suppose there is such a Class
.
The following example
package com.demo;
+
+public class BaseTest {
+
+ public BaseTest() {
+ // ...
+ }
+
+ public BaseTest(boolean isInit) {
+ // ...
+ }
+
+ private void doBaseTask(String taskName) {
+ // ...
+ }
+}
+
package com.demo;
+
+public class Test extends BaseTest {
+
+ public Test() {
+ // ...
+ }
+
+ public Test(boolean isInit) {
+ // ...
+ }
+
+ private static TAG = "Test";
+
+ private BaseTest baseInstance;
+
+ private String a;
+
+ private boolean a;
+
+ private boolean isTaskRunning = false;
+
+ private static void init() {
+ // ...
+ }
+
+ private void doTask(String taskName) {
+ // ...
+ }
+
+ private void release(String taskName, Function<boolean, String> task, boolean isFinish) {
+ // ...
+ }
+
+ private void stop() {
+ // ...
+ }
+
+ private String getName() {
+ // ...
+ }
+
+ private void b() {
+ // ...
+ }
+
+ private void b(String a) {
+ // ...
+ }
+}
+
Suppose we want to get the doTask
method of Test
and execute it.
Normally, we can use the standard reflection API to find this method.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using reflection API
+Test::class.java
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(instance, "task_name")
+
This is probably not very friendly, and YukiReflection
provides you with a syntactic sugar that can be used anywhere.
The above writing can be written as YukiReflection
as follows.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doTask"
+ param(StringClass)
+}.get(instance).call("task_name")
+
Tips
For more features, please refer to MethodFinder.
Similarly, we need to get the isTaskRunning
field can also be written as follows.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.field {
+ name = "isTaskRunning"
+ type = BooleanType
+}.get(instance).any() // Any instantiates an object of any type of Field
+
Tips
For more features, please refer to FieldFinder.
Maybe you also want to get the current Class
constructor, the same can be achieved.
The following example
Test::class.java.constructor {
+ param(BooleanType)
+}.get().call(true) // Can create a new instance
+
If you want to get the no-argument constructor of Class
, you can write it as follows.
The following example
Test::class.java.constructor().get().call() // Create a new instance
+
Tips
For more features, please refer to ConstructorFinder.
Suppose we want to get the getName
method in Class
, which can be implemented as follows.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+ returnType = StringClass
+}.get(instance).string() // Get the result of the method
+
Through observation, it is found that there is only one method named getName
in this Class
, so can we make it simpler?
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+}.get(instance).string() // Get the result of the method
+
Yes, you can refine your find criteria for methods that do not change exactly.
When using only get
or wait
methods to get results, YukiReflection
will match the first found result in bytecode order by default.
The problem comes again, this Class
has a release
method, but its method parameters are very long, and some types may not be directly available.
Normally we would use param(...)
to find this method, but is there an easier way.
At this point, after determining the uniqueness of the method, you can use paramCount
to find the method.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "release"
+ // At this point
+ // We don't have to determine the specific type of method parameters, just write the number
+ paramCount = 3
+}.get(instance) // Get this method
+
Although the above example can be successfully matched, it is not accurate.
At this time, you can also use VagueType
to fill in the method parameter type that you do not want to fill in.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "release"
+ // Use VagueType to fill in the type you don't want to fill in
+ // While ensuring that other types can match
+ param(StringClass, VagueType, BooleanType)
+}.get(instance) // Get this method
+
If you are not sure about the type of each parameter, you can create a conditional method body with the param { ... }
method.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "release"
+ // Get the it (Class) method parameter type array instance
+ // To only determine the known type and its position
+ param { it[0] == StringClass && it[2] == BooleanType }
+}.get(instance) // Get this method
+
Tips
Use param { ... } to create a conditional method body, where the variable it is the Class type array instance of the current method parameter, and you can freely use Class all objects and their methods in.
The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result.
For more functions, please refer to FieldFinder.type, MethodFinder.param, MethodFinder.returnType, ConstructorFinder.param method.
You will notice that Test
extends BaseTest
, now we want to get the doBaseTask
method of BaseTest
, how do we do it without knowing the name of the super class?
Referring to the above find conditions, we only need to add a superClass
to the find conditions to achieve this function.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringClass)
+ // Just add this condition
+ superClass()
+}.get(instance).call("task_name")
+
At this time, we can get this method in the super class.
superClass
has a parameter isOnlySuperClass
, when set to true
, you can skip the current Class
and only find the super class of the current Class
.
Since we now know that the doBaseTask
method only exists in the super class, this condition can be added to save finding time.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringClass)
+ // Add a find condition
+ superClass(isOnlySuperClass = true)
+}.get(instance).call("task_name")
+
At this time, we can also get this method in the super class.
Once superClass
is set, it will automatically cycle backward to find out whether this method exists in all extends super classes, until it finds that the target has no super class (the extends is java.lang.Object
).
Tips
For more functions, please refer to MethodFinder.superClass, ConstructorFinder.superClass, FieldFinder.superClass methods.
Pay Attention
The currently founded Method can only find the Method of the current Class unless the superClass condition is specified, which is the default behavior of the Java Reflection API.
If we want to find a method name, but are not sure if it has changed in each release, we can use vague find.
Suppose we want to get the doTask
method in Class
, which can be implemented as follows.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name {
+ // Set name is case insensitive
+ it.equals("dotask", isIgnoreCase = true)
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
Knowing that there is currently only one doTask
method in Class
, we can also judge that the method name contains only the characters specified in it.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name {
+ // Only contains oTas
+ it.contains("oTas")
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
We can also judge based on the first and last strings.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name {
+ // Contains do at the beginning and Task at the end
+ it.startsWith("do") && it.endsWith("Task")
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
By observing that this method name contains only letters, we can add a precise search condition.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name {
+ // Start with do, end with Task, just letters
+ it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters()
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
Tips
Use name { ... } to create a conditional method body, where the variable it is the string of the current name, and you can freely use it in the extension method of NameRules function.
The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result.
For more functions, please refer to FieldFinder.name, MethodFinder.name methods and NameRules.
Sometimes, we may need to find a set of methods, constructors, and fields with the same characteristics in a Class
.
At this time, we can use relative condition matching to complete.
Based on the result of the find condition, we only need to replace get
with all
to get all the bytecodes that match the condition.
Suppose this time we want to get all methods in Class
with the number of method parameters in the range 1..3
, you can use the following implementation.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ paramCount(1..3)
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
The above example can be perfectly matched to the following 3 methods.
private void doTask(String taskName)
private void release(String taskName, Function<boolean, String> task, boolean isFinish)
private void b(String a)
If you want to define the conditions for the range of the number of parameters more freely, you can use the following implementation.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ paramCount { it < 3 }
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
The above example can be perfectly matched to the following 6 methods.
private static void init()
private void doTask(String taskName)
private void stop(String a)
private void getName(String a)
private void b()
private void b(String a)
By observing that there are two methods named b
in Class
, you can use the following implementation.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "b"
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
The above example can be perfectly matched to the following 2 methods.
private void b()
private void b(String a)
Tips
Use paramCount { ... } to create a conditional method body, where the variable it is the integer of the current number of parameters, and you can use it freely in the extension method of CountRules function in it.
The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result.
For more functions, please refer to MethodFinder.paramCount, ConstructorFinder.paramCount methods and CountRules.
Some methods and fields are statically implemented in Class
, at this time, we can call them without passing in an instance.
Suppose we want to get the contents of the static field TAG
this time.
The following example
Test::class.java.field {
+ name = "TAG"
+ type = StringClass
+}.get().string() // The type of Field is string and can be cast directly
+
Assuming that there is a non-static TAG
field with the same name in Class
, what should I do at this time?
Just add a filter.
The following example
Test::class.java.field {
+ name = "TAG"
+ type = StringClass
+ // This field to identify the lookup needs to be static
+ modifiers { isStatic }
+}.get().string() // The type of Field is string and can be cast directly
+
We can also call a static method called init
.
The following example
Test::class.java.method {
+ name = "init"
+ emptyParam()
+}.get().call()
+
Likewise, you can identify it as a static.
The following example
Test::class.java.method {
+ name = "init"
+ emptyParam()
+ // This method of identity find needs to be static
+ modifiers { isStatic }
+}.get().call()
+
Tips
Use modifiers { ... } to create a conditional method body, at which point you can freely use its functionality in ModifierRules.
The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result.
For more functions, please refer to FieldFinder.modifiers, MethodFinder.modifiers, ConstructorFinder.modifiers methods and ModifierRules.
You may have noticed that the example Class
given here has two obfuscated field names, both of which are a
, how do we get them at this time?
There are two options.
The first option is to determine the name and type of the field.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.field {
+ name = "a"
+ type = BooleanType
+}.get(instance).any() // Get a field named a with type Boolean
+
The second option is to determine where the type of the field is located.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.field {
+ type(BooleanType).index().first()
+}.get(instance).any() // Get the first field of type Boolean
+
In the above two cases, the corresponding field private boolean a
can be obtained.
Likewise, there are two obfuscated method names in this Class
, both of which are b
.
You can also have two options to get them.
The first option is to determine the method name and method parameters.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "b"
+ param(StringClass)
+}.get(instance).call("test_string") // Get the method whose name is b and whose parameter is [String]
+
The second option is to determine where the parameters of the method are located.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ param(StringClass).index().first()
+}.get(instance).call("test_string") // Get the method whose first method parameter is [String]
+
Since it is observed that this method is last in Class
, then we have an alternative.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ order().index().last()
+}.get(instance).call("test_string") // Get the last method of the current Class
+
Notice
Please try to avoid using order to filter bytecode subscripts, they may be indeterminate unless you are sure that its position in this Class must not change.
The methods of calling bytecode described above all need to use get(instance)
to call the corresponding method.
Is there a simpler way?
At this point, you can use the current
method on any instance to create a call space.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // Execute the doTask method
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+ // Execute the stop method
+ method {
+ name = "stop"
+ emptyParam()
+ }.call()
+ // Get name
+ val name = method { name = "getName" }.string()
+}
+
We can also use superClass
to call methods of the current Class
super class.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // Execute the doBaseTask method of the parent class
+ superClass().method {
+ name = "doBaseTask"
+ param(StringClass)
+ }.call("task_name")
+}
+
If you don't like to use a lambda to create the namespace of the current instance, you can use the current()
method directly.
The following example
// Assuming this is an instance of this Class, this Class cannot be obtained directly
+val instance = Test()
+// Execute the doTask method
+instance
+ .current()
+ .method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+// Execute the stop method
+instance
+ .current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// Get name
+val name = instance.current().method { name = "getName" }.string()
+
Likewise, consecutive calls can be made between them, but inline calls are not allowed.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+}.current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// Note that because current() returns the CurrentClass object itself
+// It CANNOT BE CALLED like the following
+instance.current().current()
+
For Field
instances, there is also a convenience method that can directly get the object of the instance where Field
is located.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // <Plan 1>
+ field {
+ name = "baseInstance"
+ }.current {
+ method {
+ name = "doBaseTask"
+ param(StringClass)
+ }.call("task_name")
+ }
+ // <Plan 2>
+ field {
+ name = "baseInstance"
+ }.current()
+ ?.method {
+ name = "doBaseTask"
+ param(StringClass)
+ }?.call("task_name")
+}
+
Notice
The above current method is equivalent to calling the field { ... }.any()?.current() method in CurrentClass for you.
If there is no CurrentClass calling field, you need to use field { ... }.get(instance).current() to call it.
The problem comes again, I want to use reflection to create the following instance and call the method in it, how to do it?
The following example
Test(true).doTask("task_name")
+
Usually, we can use the standard reflection API to call.
The following example
"com.demo.Test".toClass()
+ .getDeclaredConstructor(Boolean::class.java)
+ .apply { isAccessible = true }
+ .newInstance(true)
+ .apply {
+ javaClass
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(this, "task_name")
+ }
+
But I feel that this approach is very troublesome.
Is there a more concise way to call it?
At this time, we can also use the buildOf
method to create an instance.
The following example
"com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+}
+
If you want the buildOf
method to return the type of the current instance, you can include a type-generic declaration in it instead of using as
to cast
the target type.
In this case, the constructor of the instance itself is private, but the method inside is public, so we only need to create its constructor by reflection.
The following example
// Assume this Class can be obtained directly
+val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
+test.doTask("task_name")
+
Tips
For more functions, please refer to CurrentClass and Class.buildOf method.
Suppose there are three different versions of Class
, all of which are the same Class
for different versions of this app.
There is also a method doTask
in it, assuming they function the same.
The following example of version A
public class Test {
+
+ public void doTask() {
+ // ...
+ }
+}
+
The following example of version B
public class Test {
+
+ public void doTask(String taskName) {
+ // ...
+ }
+}
+
The following example of version C
public class Test {
+
+ public void doTask(String taskName, int type) {
+ // ...
+ }
+}
+
We need to get this same functionality of the doTask
method in a different version, how do we do it?
At this point, you can use RemedyPlan
to complete your needs.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+ method {
+ name = "doTask"
+ param(StringClass, IntType)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+}.wait(instance) {
+ // Get the result of the method
+}
+
Pay Attention
The method lookup result using RemedyPlan can no longer use get to get method instance, you should use wait method.
Also, you can continue to use RemedyPlan
while using Multiple Find.
The following example
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiReflection
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+}.waitAll(instance) {
+ // Get the result of the method
+}
+
Tips
For more functions, please refer to MethodFinder.RemedyPlan, ConstructorFinder.RemedyPlan, FieldFinder.RemedyPlan .
Suppose there is a Class
with the same function in different versions of the current app but only the name of the Class
is different.
The following example of version A
public class ATest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
The following example of version B
public class BTest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
At this time, what should we do if we want to call the doTask
method in this Class
in each version?
The usual practice is to check if Class
exists.
The following example
// First find this Class
+val currentClass =
+ if("com.demo.ATest".hasClass()) "com.demo.ATest".toClass() else "com.demo.BTest".toClass()
+// Then look for this method and call
+currentClass.method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
I feel that this solution is very inelegant and cumbersome, then YukiReflection
provides you with a very convenient VariousClass
to solve this problem.
Now, you can get this Class
directly using the following methods.
The following example
VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
If the current Class
exists in the specified ClassLoader
, you can fill in your ClassLoader
in get
.
The following example
val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
If you are not sure that all Class
will be matched, you can use the getOrNull
method.
The following example
val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
+ name = "doTask"
+ emptyParam()
+}?.get()?.call()
+
Tips
For more functions, please refer to VariousClass.
In the process of reflection, we may encounter generic problems.
In the reflection processing of generics, YukiReflection
also provides a syntactic sugar that can be used anywhere.
For example we have the following generic class.
The following example
class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // ...
+ }
+}
+
When we want to get a Class
instance of the generic T
or R
in the current Class
, only the following implementation is required.
The following example
class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // Get the operation object of the current instance
+ // Get the Class instance of T, in the 0th position of the parameter
+ // The default value can not be written
+ val tClass = current().generic()?.argument()
+ // Get the Class instance of R, in parameter 1
+ val rClass = current().generic()?.argument(index = 1)
+ // You can also use the following syntax
+ current().generic {
+ // Get the Class instance of T
+ // In the 0th position of the parameter, the default value can be left blank
+ val tClass = argument()
+ // Get the Class instance of R, in parameter 1
+ val rClass = argument(index = 1)
+ }
+ }
+}
+
When we want to call this Class
externally, it can be implemented as follows.
The following example
// Assume this is the Class of T
+class TI {
+
+ fun foo() {
+ // ...
+ }
+}
+// Assume this is an instance of T
+val tInstance: TI? = ...
+// Get the Class instance of T
+// In the 0th position of the parameter, the default value can be left blank
+// And get the method foo and call it
+TestGeneric::class.java.generic()?.argument()?.method {
+ name = "foo"
+ emptyParam()
+}?.get(tInstance)?.invoke<TI>()
+
Tips
For more functions, please refer to CurrentClass.generic, Class.generic methods and GenericClass.
Here are some misunderstandings that may be encountered during use for reference.
In find conditions you can only use index
function once except order
.
The following example
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ // Wrong usage, please keep only one index method
+ returnType(StringClass).index(num = 1)
+}
+
The following find conditions can be used without any problems.
The following example
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ order().index(num = 1)
+}
+
In common method find conditions, even methods without parameters need to set find conditions.
Suppose we have the following Class
.
The following example
public class TestFoo {
+
+ public void foo(String string) {
+ // ...
+ }
+
+ public void foo() {
+ // ...
+ }
+}
+
We want to get the public void foo()
method, which can be written as follows.
The following example
TestFoo::class.java.method {
+ name = "foo"
+}
+
However, the above example is wrong.
You will find two foo
methods in this Class
, one of which takes a method parameter.
Since the above example does not set the find conditions for param
, the result will be the first method public void foo(String string)
that matches the name and matches the bytecode order, not the last method we need.
This is a frequent error, without method parameters, you will lose the use of method parameter find conditions.
The correct usage is as follows.
The following example
TestFoo::class.java.method {
+ name = "foo"
+ // ✅ Correct usage, add detailed filter conditions
+ emptyParam()
+}
+
At this point, the above example will perfectly match the public void foo()
method.
Compatibility Notes
In the past historical versions of the API, it was allowed to match the method without writing the default matching no-parameter method, but the latest version has corrected this problem, please make sure that you are using the latest API version.
In the find conditions for constructors, even constructors without parameters need to set find conditions.
Suppose we have the following Class
.
The following example
public class TestFoo {
+
+ public TestFoo() {
+ // ...
+ }
+}
+
To get the public TestFoo()
constructor, we must write it in the following form.
The following example
TestFoo::class.java.constructor { emptyParam() }
+
The above example can successfully obtain the public TestFoo()
constructor.
If you write constructor()
and miss emptyParam()
, the result found at this time will be the first one in bytecode order, may not be parameterless.
Compatibility Notes
In past historical versions of the API, if the constructor does not fill in any search parameters, the constructor will not be found directly.
This is a BUG and has been fixed in the latest version, please make sure you are using the latest API version.
API Behavior Changes
In 1.2.0 and later versions, the behavior of constructor() is no longer constructor { emptyParam() } but constructor {}, please pay attention to the behavior change reasonably adjust the find parameters.
Without setting find conditions, using field()
, constructor()
, method()
will return all members under the current Class
.
Using get(...)
or give()
will only get the first bit in bytecode order.
The following example
Test::class.java.field().get(...)
+Test::class.java.method().give()
+
If you want to get all members, you can use all(...)
or giveAll()
The following example
Test::class.java.field().all(...)
+Test::class.java.method().giveAll()
+
Compatibility Notes
In past historical versions of the API, failure to set find conditions will throw an exception.
This feature was added in 1.2.0 and later versions.
In the bytecode call result, the cast method can only specify the type corresponding to the bytecode.
For example we want to get a field of type Boolean
and cast it to String
.
The following is the wrong way to use it.
The following example
field {
+ name = "test"
+ type = BooleanType
+}.get().string() // Wrong usage, must be cast to the bytecode target type
+
The following is the correct way to use it.
The following example
field {
+ name = "test"
+ type = BooleanType
+}.get().boolean().toString() // ✅ The correct way to use, get the type and then convert
+
When find methods and fields, we usually need to specify the type in find conditions.
The following example
field {
+ name = "test"
+ type = Boolean::class.javaPrimitiveType
+}
+
Expressing the type of Boolean::class.javaPrimitiveType
in Kotlin is very long and inconvenient.
Therefore, YukiReflection
encapsulates common type calls for developers, including Android related types and Java common types and primitive type keywords.
At this time, the above type can be written in the following form.
The following example
field {
+ name = "test"
+ type = BooleanType
+}
+
The primitive type keywords in common Java types have been encapsulated as Type(Class Name) + Type, such as IntType
, FloatType
(their bytecode types are int
, float
).
Correspondingly, array types also have convenient usage methods, assuming we want to get an array of type String[]
.
You need to write java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
to get this type.
Does it feel very troublesome, at this time we can use the method ArrayClass(StringClass)
to get this type.
At the same time, since String
is a common type, you can also directly use StringArrayClass
to get this type.
The methods found in some common requirements have their corresponding encapsulation types for use, in the format Type(Class Name) + Class.
The following are wrapper names for some special case types in Java represented in YukiReflection
.
void
→ UnitType
java.lang.Void
→ UnitClass
java.lang.Object
→ AnyClass
java.lang.Integer
→ IntClass
java.lang.Character
→ CharClass
Notice
Encapsulating types with Type(Class Name) + Type will and only be represented as Java primitive type keywords.
Since the concept of primitive types does not exist in Kotlin, they will all be defined as KClass.
There are 9 primitive type keywords in Java, of which 8 are primitive type, namely boolean, char, byte, short , int, float, long, double, of which the void type is a special case.
At the same time, they all have their own corresponding package types in Java, such as java.lang.Boolean, java.lang.Integer, these types are unequal, Please note the distinction.
Similarly, arrays also have corresponding wrapper types, which also need to be distinguished from Java primitive type keywords.
For example, the encapsulation type of byte[] is ByteArrayType or ArrayClass(ByteType), and the encapsulation type of Byte[] is ByteArrayClass or ArrayClass(ByteClass), these types are also unequal.
Tips
For more types, see ComponentTypeFactory, GraphicsTypeFactory, ViewTypeFactory, VariableTypeFactory.
At the same time, you are welcome to contribute more commonly used types.
The document here will synchronize the relevant usage of the latest API version, please keep
YukiReflection
as the latest version to use the latest version of the function.
The function description mainly introduces the related usage and purpose of the current API.
The function examples mainly show the basic usage examples of the current API for reference.
The function of the first version will be marked as v<version>
first
;
New function added later will be marked as v<version>
added
;
Later modified function will be appended as v<version>
modified
;
Later deprecated function will be marked as v<version>
deprecated
and strikethrough;
Later removed function will be marked as v<version>
removed
and strikethrough.
kt Kotlin Static File
annotation Annotation Class
interface Interface Class
object Class (Singleton)
class Class
field Field or get
/ set
method or read-only get
method
method Method
enum Enum constant
ext-field Extension field (global)
ext-method Extension method (global)
i-ext-field Extension field (internal)
i-ext-method Extension method (internal)
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
object YukiReflection
+
Change Records
v1.0.0
first
Function Illustrate
这是
YukiReflection
的装载调用类。
const val TAG: String
+
Change Records
v1.0.3
added
Function Illustrate
获取当前
YukiReflection
的名称 (标签)。
const val VERSION: String
+
Change Records
v1.0.3
added
Function Illustrate
获取当前
YukiReflection
的版本。
Change Records
v1.0.0
first
v1.0.3
deprecated
不再区分版本名称和版本号,请迁移到 VERSION
Change Records
v1.0.0
first
v1.0.3
deprecated
不再区分版本名称和版本号,请迁移到 VERSION
object Configs
+
Change Records
v1.0.0
first
Function Illustrate
对 API 相关功能的配置类。
inline fun debugLog(initiate: YLog.Configs.() -> Unit)
+
Change Records
v1.0.3
added
Function Illustrate
配置
YLog.Configs
相关参数。
Change Records
v1.0.0
first
v1.0.3
deprecated
请迁移到 debugLog
var isDebug: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否启用 Debug 模式。
默认不启用,启用后将交由日志输出管理器打印详细日志 (例如反射查找功能的耗时) 到控制台。
Change Records
v1.0.0
first
v1.0.3
deprecated
请迁移到 debugLog
Change Records
v1.0.0
first
v1.0.2
deprecated
Member
的直接缓存功能已被移除,因为其存在内存溢出 (OOM) 问题
inline fun configs(initiate: Configs.() -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
对
Configs
类实现了一个 lambda 方法体。
你可以轻松地调用它进行配置。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class CurrentClass internal constructor(private val classSet: Class<*>, internal val instance: Any)
+
Change Records
v1.0.0
first
Function Illustrate
当前实例的类操作对象。
val name: String
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
classSet
的Class.getName
。
val simpleName: String
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
classSet
的Class.getSimpleName
。
fun generic(): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例中的泛型父类。
如果当前实例不存在泛型将返回 null
。
fun superClass(): SuperClass
+
Change Records
v1.0.0
first
Function Illustrate
调用父类实例。
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
Change Records
v1.0.0
first
Function Illustrate
调用当前实例中的变量。
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
Change Records
v1.0.0
first
Function Illustrate
调用当前实例中的方法。
inner class SuperClass internal constructor(private val superClassSet: Class<*>)
+
Change Records
v1.0.0
first
Function Illustrate
当前类的父类实例的类操作对象。
val name: String
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
classSet
中父类的Class.getName
。
val simpleName: String
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
classSet
中父类的Class.getSimpleName
。
fun generic(): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例父类中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例父类中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
Change Records
v1.0.0
first
Function Illustrate
调用父类实例中的变量。
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
Change Records
v1.0.0
first
Function Illustrate
调用父类实例中的方法。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class GenericClass internal constructor(private val type: ParameterizedType)
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
的泛型父类操作对象。
fun argument(index: Int): Class<*>?
+
inline fun <reified T> argument(index: Int): Class<T>?
+
Change Records
v1.0.0
first
v1.0.3
modified
方法的返回值可为 null
Function Illustrate
获得泛型参数数组下标的
Class
实例。
Notice
在运行时局部变量的泛型会被擦除,获取不到时将会返回 null。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class VariousClass(private vararg val name: String)
+
Change Records
v1.0.0
first
Function Illustrate
这是一个不确定性
Class
类名装载器,通过name
装载Class
名称数组。
fun get(loader: ClassLoader? = null, initialize: Boolean): Class<*>
+
Change Records
v1.0.0
first
Function Illustrate
获取匹配的实体类。
使用当前 loader
装载目标 Class
。
fun getOrNull(loader: ClassLoader? = null, initialize: Boolean): Class<*>?
+
Change Records
v1.0.0
first
Function Illustrate
获取匹配的实体类。
使用当前 loader
装载目标 Class
。
匹配不到 Class
会返回 null
,不会抛出异常。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
这是自定义
Member
和Class
相关功能的查找匹配以及invoke
的封装类。
open class LazyClass<T> internal constructor(
+ private val instance: Any,
+ private val initialize: Boolean,
+ private val loader: ClassLoaderInitializer?
+)
+
Change Records
v1.2.0
added
Function Illustrate
懒装载
Class
实例。
fun ClassLoader.listOfClasses(): List<String>
+
Change Records
v1.0.0
first
Function Illustrate
写出当前
ClassLoader
下所有Class
名称数组。
inline fun ClassLoader.searchClass(context: Context?, name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
Change Records
v1.0.0
first
Function Illustrate
通过当前
ClassLoader
按指定条件查找并得到 Dex 中的Class
。
Pay Attention
此方法在 Class 数量过多及查找条件复杂时会非常耗时。
建议启用 async 或设置 name 参数,name 参数将在当前 APP 不同版本中自动进行本地缓存以提升效率。
如果使用了 async 或 name 参数,则必须填写 context 参数。
此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
val Class<*>.hasExtends: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否有继承关系,父类是Any
将被认为没有继承关系。
infix fun Class<*>?.extends(other: Class<*>?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否继承于other
。
如果当前 Class
就是 other
也会返回 true
。
如果当前 Class
为 null
或 other
为 null
会返回 false
。
Function Example
你可以使用此方法来判断两个 Class
是否存在继承关系。
The following example
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否继承于 B
+if (classA extends classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.notExtends(other: Class<*>?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否不继承于other
。
此方法相当于 extends
的反向判断。
Function Example
你可以使用此方法来判断两个 Class
是否不存在继承关系。
The following example
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否不继承于 B
+if (classA notExtends classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.implements(other: Class<*>?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否实现了other
接口类。
如果当前 Class
为 null
或 other
为 null
会返回 false
。
Function Example
你可以使用此方法来判断两个 Class
是否存在依赖关系。
The following example
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否实现了 B 接口类
+if (classA implements classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.notImplements(other: Class<*>?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
当前
Class
是否未实现other
接口类。
此方法相当于 implements
的反向判断。
Function Example
你可以使用此方法来判断两个 Class
是否不存在依赖关系。
The following example
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否未实现 B 接口类
+if (classA notImplements classB) {
+ // Your code here.
+}
+
fun Class<*>.toJavaPrimitiveType(): Class<*>
+
Change Records
v1.0.0
first
Function Illustrate
自动转换当前
Class
为 Java 原始类型 (Primitive Type)。
如果当前 Class
为 Java 或 Kotlin 基本类型将自动执行类型转换。
当前能够自动转换的基本类型如下。
kotlin.Unit
java.lang.Void
java.lang.Boolean
java.lang.Integer
java.lang.Float
java.lang.Double
java.lang.Long
java.lang.Short
java.lang.Character
java.lang.Byte
fun String.toClass(loader: ClassLoader?, initialize: Boolean): Class<*>
+
inline fun <reified T> String.toClass(loader: ClassLoader?, initialize: Boolean): Class<T>
+
Change Records
v1.0.0
first
Function Illustrate
通过字符串类名转换为
loader
中的实体类。
Function Example
你可以直接填写你要查找的目标 Class
,必须在默认 ClassLoader
下存在。
The following example
"com.example.demo.DemoClass".toClass()
+
你还可以自定义 Class
所在的 ClassLoader
。
The following example
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
你还可以指定 Class
的目标类型。
The following example
// 指定的 DemoClass 必须存在或为可访问的 stub
+"com.example.demo.DemoClass".toClass<DemoClass>()
+
你还可以设置在获取到这个 Class
时是否自动执行其默认的静态方法块,默认情况下不会执行。
The following example
// 获取并执行 DemoClass 默认的静态方法块
+"com.example.demo.DemoClass".toClass(initialize = true)
+
默认的静态方法块在 Java 中使用如下方式定义。
The following example
public class DemoClass {
+
+ static {
+ // 这里是静态方法块的内容
+ }
+
+ public DemoClass() {
+ // ...
+ }
+}
+
fun String.toClassOrNull(loader: ClassLoader?, initialize: Boolean): Class<*>?
+
inline fun <reified T> String.toClassOrNull(loader: ClassLoader?, initialize: Boolean): Class<T>?
+
Change Records
v1.0.0
first
Function Illustrate
通过字符串类名转换为
loader
中的实体类。
找不到 Class
会返回 null
,不会抛出异常。
Function Example
用法请参考 String.toClass 方法。
inline fun <reified T> classOf(loader: ClassLoader?, initialize: Boolean): Class<T>
+
Change Records
v1.0.0
first
Function Illustrate
通过
T
得到其Class
实例并转换为实体类。
Function Example
我们要获取一个 Class
在 Kotlin 下不通过反射时应该这样做。
The following example
DemoClass::class.java
+
现在,你可以直接 cast
一个实例并获取它的 Class
对象,必须在当前 ClassLoader
下存在。
The following example
classOf<DemoClass>()
+
若目标存在的 Class
为 stub
,通过这种方式,你还可以自定义 Class
所在的 ClassLoader
。
The following example
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+classOf<DemoClass>(customClassLoader)
+
fun lazyClass(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<Any>
+
inline fun <reified T> lazyClass(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<T>
+
fun lazyClass(variousClass: VariousClass, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<Any>
+
Change Records
v1.0.3
added
Function Illustrate
懒装载
Class
。
fun lazyClassOrNull(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<Any>
+
inline fun <reified T> lazyClassOrNull(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<T>
+
fun lazyClassOrNull(variousClass: VariousClass, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<Any>
+
Change Records
v1.0.3
added
Function Illustrate
懒装载
Class
。
fun String.hasClass(loader: ClassLoader?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
通过字符串类名使用指定的
ClassLoader
查找是否存在。
Function Example
你可以轻松的使用此方法判断字符串中的类是否存在,效果等同于直接使用 Class.forName
。
The following example
if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
填入方法中的 loader
参数可判断指定的 ClassLoader
中的 Class
是否存在。
The following example
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找变量是否存在。
inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找方法是否存在。
inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找构造方法是否存在。
inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找
Member
中匹配的描述符。
inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
查找
Class
中匹配的描述符。
inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
+
Change Records
v1.0.0
first
Function Illustrate
查找并得到变量。
inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
+
Change Records
v1.0.0
first
Function Illustrate
查找并得到方法。
inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
Change Records
v1.0.0
first
Function Illustrate
查找并得到构造方法。
fun Class<*>.generic(): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
Class
的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
Class
的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun <reified T : Any> T.current(ignored: Boolean): CurrentClass
+
inline fun <reified T : Any> T.current(ignored: Boolean, initiate: CurrentClass.() -> Unit): T
+
Change Records
v1.0.0
first
Function Illustrate
获得当前实例的类操作对象。
inline fun Class<*>.buildOf(vararg args: Any?, initiate: ConstructorConditions): Any?
+
inline fun <T> Class<*>.buildOf(vararg args: Any?, initiate: ConstructorConditions): T?
+
Change Records
v1.0.0
first
Function Illustrate
通过构造方法创建新实例,指定类型
T
或任意类型Any
。
inline fun Class<*>.allMethods(isAccessible: Boolean, result: (index: Int, method: Method) -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
遍历当前类中的所有方法。
inline fun Class<*>.allConstructors(isAccessible: Boolean, result: (index: Int, constructor: Constructor<*>) -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
遍历当前类中的所有构造方法。
inline fun Class<*>.allFields(isAccessible: Boolean, result: (index: Int, field: Field) -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
遍历当前类中的所有变量。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
abstract class BaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
这是
Class
与Member
查找类功能的基本类实现。
inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
+
Change Records
v1.0.0
first
Function Illustrate
字节码下标筛选实现类。
fun index(num: Int)
+
Change Records
v1.0.0
first
Function Illustrate
设置下标。
若 index
小于零则为倒序,此时可以使用 IndexTypeConditionSort.reverse
方法实现。
可使用 IndexTypeConditionSort.first
和 IndexTypeConditionSort.last
设置首位和末位筛选条件。
fun index(): IndexTypeConditionSort
+
Change Records
v1.0.0
first
Function Illustrate
得到下标。
inner class IndexTypeConditionSort internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
字节码下标排序实现类。
fun first()
+
Change Records
v1.0.0
first
Function Illustrate
设置满足条件的第一个。
fun last()
+
Change Records
v1.0.0
first
Function Illustrate
设置满足条件的最后一个。
fun reverse(num: Int)
+
Change Records
v1.0.0
first
Function Illustrate
设置倒序下标。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class CountRules private constructor()
+
Change Records
v1.0.0
first
Function Illustrate
这是一个模糊
Class
、Member
数组 (下标) 个数条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
fun Int.isZero(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否为 0。
fun Int.moreThan(count: Int): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
大于
count
。
fun Int.lessThan(count: Int): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
小于
count
。
fun Int.inInterval(countRange: IntRange): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
在
countRange
区间 A ≤ this ≤ B。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ModifierRules private constructor()
+
Change Records
v1.0.0
first
Function Illustrate
这是一个
Class
、Member
描述符条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
val isPublic: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含public
。
val isPrivate: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含private
。
val isProtected: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含protected
。
val isStatic: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含static
。
对于任意的静态 Class
、Member
可添加此描述进行确定。
Notice
Kotlin → Jvm 后的 object 类中的方法并不是静态的。
val isFinal: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含final
。
Notice
Kotlin → Jvm 后没有 open 符号标识的 Class、Member 和没有任何关联的 Class、Member 都将为 final。
val isSynchronized: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含synchronized
。
val isVolatile: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Field
类型是否包含volatile
。
val isTransient: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Field
类型是否包含transient
。
val isNative: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Method
类型是否包含native
。
对于任意 JNI 对接的 Method
可添加此描述进行确定。
val isInterface: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
类型是否包含interface
。
val isAbstract: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含abstract
。
对于任意的抽象 Class
、Member
可添加此描述进行确定。
val isStrict: Boolean
+
Change Records
v1.0.0
first
Function Illustrate
Class
、Member
类型是否包含strictfp
。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class NameRules private constructor()
+
Change Records
v1.0.0
first
Function Illustrate
这是一个模糊
Class
、Member
名称条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
fun String.isSynthetic(index: Int): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否为匿名类的主类调用对象。
fun String.isOnlySymbols(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有符号。
fun String.isOnlyLetters(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有字母。
fun String.isOnlyNumbers(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有数字。
fun String.isOnlyLettersNumbers(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有字母或数字。
fun String.isOnlyLowercase(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有小写字母。
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
fun String.isOnlyUppercase(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
是否只有大写字母。
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ObjectRules private constructor(private val instance: Any)
+
Change Records
v1.0.0
first
Function Illustrate
这是一个任意对象条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class DexClassFinder internal constructor(
+ private val context: Context?,
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
Class
查找类。
可使用 BaseDexClassLoader
通过指定条件查找指定 Class
或一组 Class
。
Notice
此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
Change Records
v1.0.0
first
fun clearCache(context: Context, versionName: String?, versionCode: Long?)
+
Change Records
v1.0.0
first
Function Illustrate
清除当前
DexClassFinder
的Class
缓存。
适用于全部通过 ClassLoader.searchClass 获取的 DexClassFinder
。
var fullName: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
完整名称。
只会查找匹配到的 Class.getName
。
例如 com.demo.Test
需要填写 com.demo.Test
。
var simpleName: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
简单名称。
只会查找匹配到的 Class.getSimpleName
。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
会为空,此时你可以使用 singleName。
var singleName: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
独立名称。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。
fun from(vararg name: String): FromPackageRules
+
Change Records
v1.0.0
first
Function Illustrate
设置在指定包名范围查找当前
Class
。
设置后仅会在当前 name
开头匹配的包名路径下进行查找,可提升查找速度。
例如 ↓
com.demo.test
com.demo.test.demo
Notice
建议设置此参数指定查找范围,否则 Class 过多时将会非常慢。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
标识符筛选条件。
可不设置筛选条件。
fun fullName(value: String): ClassNameRules
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
完整名称。
只会查找匹配到的 Class.getName
。
例如 com.demo.Test
需要填写 com.demo.Test
。
fun simpleName(value: String): ClassNameRules
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
简单名称。
只会查找匹配到的 Class.getSimpleName
。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest 会为空
,此时你可以使用 singleName。
fun singleName(value: String): ClassNameRules
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
独立名称。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。
fun fullName(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
完整名称条件。
只会查找匹配到的 Class.getName
。
fun simpleName(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
简单名称条件。
只会查找匹配到的 Class.getSimpleName
。
fun singleName(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
独立名称条件。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
inline fun <reified T> extends()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
继承的父类。
fun extends(vararg name: String)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
继承的父类。
会同时查找 name
中所有匹配的父类。
inline fun <reified T> implements()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
实现的接口类。
fun implements(vararg name: String)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
实现的接口类。
会同时查找 name
中所有匹配的接口类。
fun anonymous()
+
Change Records
v1.0.0
first
Function Illustrate
标识
Class
为匿名类。
例如 com.demo.Test$1
或 com.demo.Test$InnerTest
。
标识后你可以使用 enclosing 来进一步指定匿名类的 (封闭类) 主类。
fun noExtends()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
没有任何继承。
此时 Class
只应该继承于 Any
。
Notice
设置此条件后 extends 将失效。
fun noImplements()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
没有任何接口。
Notice
设置此条件后 implements 将失效。
fun noSuper()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
没有任何继承与接口。
此时 Class
只应该继承于 Any
。
Notice
设置此条件后 extends 与 implements 将失效。
inline fun <reified T> enclosing()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
匿名类的 (封闭类) 主类。
fun enclosing(vararg name: String)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
匿名类的 (封闭类) 主类。
会同时查找 name
中所有匹配的 (封闭类) 主类。
inner class FromPackageRules internal constructor(private val packages: MutableList<ClassRulesData.PackageRulesData>)
+
Change Records
v1.0.0
first
Function Illustrate
包名范围名称过滤匹配条件实现类。
fun absolute()
+
Change Records
v1.0.0
first
Function Illustrate
设置包名绝对匹配。
例如有如下包名 ↓
com.demo.test.a
com.demo.test.a.b
com.demo.test.active
若包名条件为 com.demo.test.a
则绝对匹配仅能匹配到第一个。
相反地,不设置以上示例会全部匹配。
inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
+
Change Records
v1.0.0
first
Function Illustrate
类名匹配条件实现类。
fun optional()
+
Change Records
v1.0.0
first
Function Illustrate
设置类名可选。
例如有如下类名 ↓
com.demo.Test
fullName / Test
simpleName
defpackage.a
fullName / a
simpleName
这两个类名都是同一个类,但是在有些版本中被混淆有些版本没有。
此时可设置类名为 com.demo.Test
fullName / Test
simpleName。
这样就可在完全匹配类名情况下使用类名而忽略其它查找条件,否则忽略此条件继续使用其它查找条件。
inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
满足的Member
条件。
inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
满足的Field
条件。
inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
满足的Method
条件。
inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置
Class
满足的Constructor
条件。
inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
+
Change Records
v1.0.0
first
Function Illustrate
Class
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建监听结果事件方法体。
fun get(): Class<*>?
+
Change Records
v1.0.0
first
Function Illustrate
得到
Class
本身。
若有多个 Class
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
若你设置了 async
请使用 wait 方法。
fun all(): MutableList<Class<*>>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Class
本身数组。
返回全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
若你设置了 async
请使用 waitAll 方法。
fun all(result: (Class<*>) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
得到
Class
本身数组 (依次遍历)。
回调全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将不会执行。
若你设置了 async
请使用 waitAll 方法。
fun wait(result: (Class<*>?) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
得到
Class
本身 (异步)。
若有多个 Class
结果只会回调第一个。
在查找条件找不到任何结果的时候将回调 null。
你需要设置 async
后此方法才会被回调,否则请使用 get 方法。
fun waitAll(result: (MutableList<Class<*>>) -> Unit): Result
+
Change Records
v1.0.0
first
v1.0.3
modified
result
类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Class
本身数组 (异步)。
回调全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将回调空的 MutableList
。
你需要设置 async
后此方法才会被回调,否则请使用 all 方法。
fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
监听找不到
Class
时。
fun ignored(): Result
+
Change Records
v1.0.0
first
Function Illustrate
忽略异常并停止打印任何错误日志。
此时若要监听异常结果,你需要手动实现 onNoClassDefFoundError 方法。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ConstructorRules internal constructor(private val rulesData: ConstructorRulesData) : BaseRules
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
查找条件实现类。
var paramCount: Int
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
标识符筛选条件。
可不设置筛选条件。
fun emptyParam()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
空参数、无参数。
fun param(vararg paramType: Any)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。
Pay Attention
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
fun param(conditions: ObjectsConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数条件。
Pay Attention
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
fun paramCount(numRange: IntRange)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
fun paramCount(conditions: CountConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class FieldRules internal constructor(private val rulesData: FieldRulesData) : BaseRules
+
Change Records
v1.0.0
first
Function Illustrate
Field
查找条件实现类。
var name: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称。
var type: Any?
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型。
可不填写类型。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
标识符筛选条件。
可不设置筛选条件。
fun name(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称条件。
fun type(conditions: ObjectConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型条件。
可不填写类型。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MemberRules internal constructor(private val rulesData: MemberRulesData) : BaseRules
+
Change Records
v1.0.0
first
Function Illustrate
Member
查找条件实现类。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Member
标识符筛选条件。
可不设置筛选条件。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MethodRules internal constructor(private val rulesData: MethodRulesData) : BaseRules
+
Change Records
v1.0.0
first
Function Illustrate
Method
查找条件实现类。
var name: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称。
var paramCount: Int
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
var returnType: Any?
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值。
可不填写返回值。
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
标识符筛选条件。
可不设置筛选条件。
fun emptyParam()
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
空参数、无参数。
fun param(vararg paramType: Any)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Method
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。
Pay Attention
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
fun param(conditions: ObjectsConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数条件。
Pay Attention
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
fun name(conditions: NameConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称条件。
fun paramCount(numRange: IntRange)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
fun paramCount(conditions: CountConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
fun returnType(conditions: ObjectConditions)
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值条件。
可不填写返回值。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
+
Change Records
v1.0.0
first
Function Illustrate
当前
Member
查找条件结果实现类。
fun none(): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Member
在查找条件中个数为0
。
fun count(num: Int): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Member
在查找条件中需要全部匹配的个数。
fun count(numRange: IntRange): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Member
在查找条件中需要全部匹配的个数范围。
fun count(conditions: CountConditions): MemberRulesResult
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Member
在查找条件中需要全部匹配的个数条件。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ConstructorFinder internal constructor(override val classSet: Class<*>) : MemberBaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
查找类。
可通过指定类型查找指定 Constructor
或一组 Constructor
。
var paramCount: Int
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
标识符筛选条件。
可不设置筛选条件,默认模糊查找并取第一个匹配的 Constructor
。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun emptyParam(): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
空参数、无参数。
fun param(vararg paramType: Any): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。
Pay Attention
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun param(conditions: ObjectsConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数条件。
Pay Attention
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(num: Int): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数。
若参数个数小于零则忽略并使用 param
。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(numRange: IntRange): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Constructor
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
Change Records
v1.0.0
first
Function Illustrate
设置在
classSet
的所有父类中查找当前Constructor
。
Notice
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
重查找实现类,可累计失败次数直到查找成功。
inline fun constructor(initiate: ConstructorConditions)
+
Change Records
v1.0.0
first
Function Illustrate
创建需要重新查找的
Constructor
。
你可以添加多个备选 Constructor
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Constructor<*>>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
modified
initiate
类型由 HashSet
修改为 MutableList
Function Illustrate
当在
RemedyPlan
中找到结果时。
Function Example
你可以方便地对重查找的 Constructor
实现 onFind
方法。
The following example
constructor {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建监听结果事件方法体。
Function Example
你可以使用 lambda 形式创建 Result
类。
The following example
constructor {
+ // Your code here.
+}.result {
+ get().call()
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
fun get(): Instance
+
Change Records
v1.0.0
first
Function Illustrate
获得
Constructor
实例处理类。
若有多个 Constructor
结果只会返回第一个。
Pay Attention
若你设置了 remedys 请使用 wait 回调结果方法。
Function Example
你可以通过获得方法所在实例来执行构造方法创建新的实例对象。
The following example
constructor {
+ // Your code here.
+}.get().call()
+
你可以 cast
构造方法为指定类型的实例对象。
The following example
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>()
+
Pay Attention
若构造方法含有参数则后方参数必填。
The following example
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>("param1", "param2")
+
fun all(): MutableList<Instance>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Constructor
实例处理类数组。
返回全部查找条件匹配的多个 Constructor
实例结果。
Function Example
你可以通过此方法来获得当前条件结果中匹配的全部 Constructor
。
The following example
constructor {
+ // Your code here.
+}.all().forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Constructor<*>?
+
Change Records
v1.0.0
first
Function Illustrate
得到
Constructor
本身。
若有多个 Constructor
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Constructor<*>>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Constructor
本身数组。
返回全部查找条件匹配的多个 Constructor
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(initiate: Instance.() -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
获得
Constructor
实例处理类,配合RemedyPlan
使用。
若有多个 Constructor
结果只会返回第一个。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(initiate: MutableList<Instance>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
modified
initiate
类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Constructor
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Constructor
实例结果。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建
Constructor
重查找功能。
Function Example
当你遇到一种 Constructor
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchConstructor
捕获异常二次查找 Constructor
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
The following example
constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
监听找不到
Constructor
时。
只会返回第一次的错误信息,不会返回 RemedyPlan
的错误信息。
fun ignored(): Result
+
Change Records
v1.0.0
first
Function Illustrate
忽略异常并停止打印任何错误日志。
Notice
此时若要监听异常结果,你需要手动实现 onNoSuchConstructor 方法。
inner class Instance internal constructor(private val constructor: Constructor<*>?)
+
Change Records
v1.0.0
first
Function Illustrate
Constructor
实例处理类。
fun call(vararg args: Any?): Any?
+
Change Records
v1.0.0
first
Function Illustrate
执行
Constructor
创建目标实例,不指定目标实例类型。
fun <T> newInstance(vararg args: Any?): T?
+
Change Records
v1.0.0
first
Function Illustrate
执行
Constructor
创建目标实例 ,指定T
目标实例类型。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class FieldFinder internal constructor(override val classSet: Class<*>?) : MemberBaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
Field
查找类。
可通过指定类型查找指定 Field
或一组 Field
。
var name: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称。
Pay Attention
若不填写名称则必须存在一个其它条件。
var type: Any?
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型。
可不填写类型。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
标识符筛选条件。
可不设置筛选条件。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun order(): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
顺序筛选字节码的下标。
fun name(value: String): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称。
Pay Attention
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun name(conditions: NameConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
名称条件。
Pay Attention
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun type(value: Any): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型。
可不填写类型。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun type(conditions: ObjectConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Field
类型条件。
可不填写类型。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
Change Records
v1.0.0
first
Function Illustrate
设置在
classSet
的所有父类中查找当前Field
。
Notice
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
Field
重查找实现类,可累计失败次数直到查找成功。
inline fun field(initiate: FieldConditions): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建需要重新查找的
Field
。
你可以添加多个备选 Field
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Field>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
modified
initiate
类型由 HashSet
修改为 MutableList
Function Illustrate
当在
RemedyPlan
中找到结果时。
Function Example
你可以方便地对重查找的 Field
实现 onFind
方法。
The following example
field {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
Change Records
v1.0.0
first
Function Illustrate
Field
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建监听结果事件方法体。
Function Example
你可以使用 lambda 形式创建 Result
类。
The following example
field {
+ // Your code here.
+}.result {
+ get(instance).set("something")
+ get(instance).string()
+ get(instance).cast<CustomClass>()
+ get().boolean()
+ all(instance)
+ give()
+ giveAll()
+ onNoSuchField {}
+}
+
fun get(instance: Any?): Instance
+
Change Records
v1.0.0
first
Function Illustrate
获得
Field
实例处理类。
若有多个 Field
结果只会返回第一个。
Function Example
你可以轻松地得到 Field
的实例以及使用它进行设置实例。
The following example
field {
+ // Your code here.
+}.get(instance).set("something")
+
如果你取到的是静态 Field
,可以不需要设置实例。
The following example
field {
+ // Your code here.
+}.get().set("something")
+
fun all(instance: Any?): MutableList<Instance>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Field
实例处理类数组。
返回全部查找条件匹配的多个 Field
实例结果。
Function Example
你可以通过此方法来获得当前条件结果中匹配的全部 Field
,其 Field
所在实例用法与 get
相同。
The following example
field {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.self
+}
+
fun give(): Field?
+
Change Records
v1.0.0
first
Function Illustrate
得到
Field
本身。
若有多个 Field 结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Field>
+
Change Records
v1.0.0
first
v1.0.3
modified
返回值类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Field
本身数组。
返回全部查找条件匹配的多个 Field
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
获得
Field
实例处理类,配合RemedyPlan
使用。
若有多个 Field
结果只会返回第一个。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(instance: Any?, initiate: MutableList<Instance>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
modified
initiate
类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Field
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Field
实例结果。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建
Field
重查找功能。
Function Example
当你遇到一种 Field
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchField
捕获异常二次查找 Field
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
The following example
field {
+ // Your code here.
+}.remedys {
+ field {
+ // Your code here.
+ }
+ field {
+ // Your code here.
+ }
+}
+
fun onNoSuchField(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
监听找不到
Field
时。
fun ignored(): Result
+
Change Records
v1.0.0
first
Function Illustrate
忽略异常并停止打印任何错误日志。
Notice
此时若要监听异常结果,你需要手动实现 onNoSuchField 方法。
inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
+
Change Records
v1.0.0
first
Function Illustrate
Field
实例变量处理类。
fun current(ignored: Boolean): CurrentClass?
+
inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
+
Change Records
v1.0.0
first
Function Illustrate
获得当前
Field
自身self
实例的类操作对象CurrentClass
。
fun <T> cast(): T?
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
实例。
fun byte(): Byte?
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Byte 实例。
fun int(): Int
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Int 实例。
fun long(): Long
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Long 实例。
fun short(): Short
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Short 实例。
fun double(): Double
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Double 实例。
fun float(): Float
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Float 实例。
fun string(): String
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
String 实例。
fun char(): Char
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Char 实例。
fun boolean(): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Boolean 实例。
fun any(): Any?
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Any 实例。
inline fun <reified T> array(): Array<T>
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
Array 实例。
inline fun <reified T> list(): List<T>
+
Change Records
v1.0.0
first
Function Illustrate
得到当前
Field
List 实例。
fun set(any: Any?)
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Field
实例。
fun setTrue()
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Field
实例为true
。
Pay Attention
请确保实例对象类型为 Boolean。
fun setFalse()
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Field
实例为false
。
Pay Attention
请确保实例对象类型为 Boolean。
fun setNull()
+
Change Records
v1.0.0
first
Function Illustrate
设置当前
Field
实例为null
。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MethodFinder internal constructor(override val classSet: Class<*>) : MemberBaseFinder
+
Change Records
v1.0.0
first
Function Illustrate
Method
查找类。
可通过指定类型查找指定 Method
或一组 Method
。
var name: String
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称。
Pay Attention
若不填写名称则必须存在一个其它条件。
var paramCount: Int
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
var returnType: Any?
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值,可不填写返回值。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
标识符筛选条件。
可不设置筛选条件。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun emptyParam(): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
空参数、无参数。
fun param(vararg paramType: Any): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Method
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。
Pay Attention
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun param(conditions: ObjectsConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数条件。
Pay Attention
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun order(): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
顺序筛选字节码的下标。
fun name(value: String): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称。
Pay Attention
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun name(conditions: NameConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
名称条件。
Pay Attention
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(num: Int): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数。
若参数个数小于零则忽略并使用 param
。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(numRange: IntRange): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun returnType(value: Any): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值。
可不填写返回值。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun returnType(conditions: ObjectConditions): IndexTypeCondition
+
Change Records
v1.0.0
first
Function Illustrate
设置
Method
返回值条件。
可不填写返回值。
Pay Attention
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
Change Records
v1.0.0
first
Function Illustrate
设置在
classSet
的所有父类中查找当前Method
。
Notice
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
Method
重查找实现类,可累计失败次数直到查找成功。
inline fun method(initiate: MethodConditions): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建需要重新查找的
Method
。
你可以添加多个备选 Method
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
Change Records
v1.0.0
first
Function Illustrate
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Method>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
修改
initiate
类型由 HashSet
修改为 MutableList
Function Illustrate
当在
RemedyPlan
中找到结果时。
Function Example
你可以方便地对重查找的 Method
实现 onFind
方法。
The following example
method {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
Change Records
v1.0.0
first
Function Illustrate
Method
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建监听结果事件方法体。
Function Example
你可以使用 lambda 形式创建 Result
类。
The following example
method {
+ // Your code here.
+}.result {
+ get(instance).call()
+ all(instance)
+ remedys {}
+ onNoSuchMethod {}
+}
+
fun get(instance: Any?): Instance
+
Change Records
v1.0.0
first
Function Illustrate
获得
Method
实例处理类。
若有多个 Method
结果只会返回第一个。
Pay Attention
若你设置了 remedys 请使用 wait 回调结果方法。
Function Example
你可以通过获得方法所在实例来执行 Method
。
The following example
method {
+ // Your code here.
+}.get(instance).call()
+
若当前为静态方法,你可以不设置实例。
The following example
method {
+ // Your code here.
+}.get().call()
+
fun all(instance: Any?): MutableList<Instance>
+
Change Records
v1.0.0
first
v1.0.3
修改
返回值类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Method
实例处理类数组。
返回全部查找条件匹配的多个 Method
实例结果。
Function Example
你可以通过此方法来获得当前条件结果中匹配的全部 Method
,其方法所在实例用法与 get
相同。
The following example
method {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Method?
+
Change Records
v1.0.0
first
Function Illustrate
得到
Method
本身。
若有多个 Method
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Method>
+
Change Records
v1.0.0
first
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
Function Illustrate
得到
Method
本身数组。
返回全部查找条件匹配的多个 Method
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
Change Records
v1.0.0
first
Function Illustrate
获得
Method
实例处理类,配合RemedyPlan
使用。
若有多个 Method
结果只会返回第一个。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(instance: Any?, initiate: MutableList<Instance>.() -> Unit)
+
Change Records
v1.0.0
first
v1.0.3
修改
initiate
类型由 ArrayList
修改为 MutableList
Function Illustrate
获得
Method
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Method
实例结果。
Pay Attention
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
创建
Method
重查找功能。
Function Example
当你遇到一种 Method
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchMethod
捕获异常二次查找 Method
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
The following example
method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.0
first
Function Illustrate
监听找不到
Method
时。
只会返回第一次的错误信息,不会返回 RemedyPlan
的错误信息。
fun ignored(): Result
+
Change Records
v1.0.0
first
Function Illustrate
忽略异常并停止打印任何错误日志。
Notice
此时若要监听异常结果,你需要手动实现 onNoSuchMethod 方法。
inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
+
Change Records
v1.0.0
first
Function Illustrate
Method
实例处理类。
fun call(vararg args: Any?): Any?
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,不指定返回值类型。
fun <T> invoke(vararg args: Any?): T?
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定T
返回值类型。
fun byte(vararg args: Any?): Byte?
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Byte 返回值类型。
fun int(vararg args: Any?): Int
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Int 返回值类型。
fun long(vararg args: Any?): Long
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Long 返回值类型。
fun short(vararg args: Any?): Short
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Short 返回值类型。
fun double(vararg args: Any?): Double
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Double 返回值类型。
fun float(vararg args: Any?): Float
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Float 返回值类型。
fun string(vararg args: Any?): String
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 String 返回值类型。
fun char(vararg args: Any?): Char
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Char 返回值类型。
fun boolean(vararg args: Any?): Boolean
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Boolean 返回值类型。
inline fun <reified T> array(vararg args: Any?): Array<T>
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 Array 返回值类型。
inline fun <reified T> list(vararg args: Any?): List<T>
+
Change Records
v1.0.0
first
Function Illustrate
执行
Method
,指定 List 返回值类型。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
object YLog
+
Change Records
v1.0.3
added
Function Illustrate
全局 Log 管理类。
object Configs
+
Change Records
v1.0.3
added
Function Illustrate
配置
YLog
。
var tag: String
+
Change Records
v1.0.3
added
Function Illustrate
这是一个调试日志的全局标识。
默认文案为 YukiReflection
。
你可以修改为你自己的文案。
var isEnable: Boolean
+
Change Records
v1.0.3
added
Function Illustrate
是否启用调试日志的输出功能。
关闭后将会停用 YukiReflection
对全部日志的输出。
当 isEnable
关闭后 YukiReflection.Configs.isDebug
也将同时关闭。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
这是一个预置反射类型的常量类,主要为
Android
相关组件的Class
内容,跟随版本更新会逐一进行增加。
详情可 点击这里 进行查看。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
这是一个预置反射类型的常量类,主要为
Android
相关Graphics
的Class
内容,跟随版本更新会逐一进行增加。
详情可 点击这里 进行查看。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
这是一个预置反射类型的常量类,主要为
Android
相关Widget
的Class
内容,跟随版本更新会逐一进行增加。
详情可 点击这里 进行查看。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
这是一个内部类型的定义常量类,主要用于反射 API 相关用法的延伸。
val VagueType: Class<*>
+
Change Records
v1.0.0
first
Function Illustrate
得到模糊类型。
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0.0
first
Function Illustrate
这是一个预置反射类型的常量类,主要为 Java 相关基本变量类型的
Class
内容,跟随版本更新会逐一进行增加。
详情可 点击这里 进行查看。
The basic configuration method of
YukiReflection
is introduced here.
YukiReflection
can be used directly without some complex configuration, and does not conflict with Java's native Reflection API.
You can configure some functions of YukiReflection
before using it.
You can get the current tag and version of YukiReflection
as follows.
The following example
// Get the tag
+val tag = YukiReflection.TAG
+// Get the version
+val version = YukiReflection.VERSION
+
You can judge the difference between different versions or display it in the about information by obtaining the version.
Tips
For more functions, please refer to YukiReflection.
You can configure related functions through YukiReflection.configs { ... }
method or YukiReflection.Configs
.
You can use the following methods to customize the tag of the debug log.
Logs inside the API will be printed using this tag.
The following example
// Via the configs method
+YukiReflection.configs {
+ debugLog {
+ tag = "YourCustomTag"
+ }
+}
+// Set directly
+YLog.Configs.tag = "YourCustomTag"
+
You can use the following methods to enable or disable Debug mode.
The Debug mode is disabled by default, and when enabled, detailed logs (such as the time spent on the reflective search function) will be printed to the console.
The following example
// Via the configs method
+YukiReflection.configs {
+ isDebug = true
+}
+// Set directly
+YukiReflection.Configs.isDebug = true
+
You can use the following methods to enable or disable debug logs.
This function is enabled by default, and disable will stop YukiReflection
output all logs.
The following example
// Via the configs method
+YukiReflection.configs {
+ debugLog {
+ isEnable = true
+ }
+}
+// Set directly
+YLog.Configs.isEnable = true
+
In order to configure multiple features at once, you can directly use the YukiReflection.configs { ... }
method to configure.
The following example
YukiReflection.configs {
+ debugLog {
+ tag = "YourCustomTag"
+ isEnable = true
+ }
+ isDebug = true
+}
+
Tips
For more functions, please refer to YukiReflection.configs method, YukiReflection.Configs.
YukiReflection
is a Reflection API based on the Java and Android platform.
This is a set of simple and efficient Reflection API rebuilt based on Java native Reflection API using Kotlin.
YukiReflection
is also the core functionality that YukiHookAPI is using.
The name is taken from "ももくり" heroine Yuki Kurihara.
YukiReflection
is fully built with Kotlin lambda syntax.
It can replace Java's native Reflection API and implement a more complete reflection solution in a more human-friendly language.
Please use Kotlin, the code composition of the API part is also compatible with Java, but the implementation of the basic reflection scene may not be used at all.
All Demo sample codes in the document will be described using Kotlin, if you don’t know how to use Kotlin at all, you may not be able to use YukiReflection
.
YukiReflection
was originally the core function integrated in the YukiHookAPI project, and now it is decoupled so that this Reflection API can be used in any Java and Android platform project.
Now, we only need to write a small amount of code to implement a simple reflection call.
With Kotlin elegant lambda and YukiReflection
, you can make your reflection logic more beautiful and clear.
The following example
"android.os.SystemProperties".toClass()
+ .method {
+ name = "get"
+ param(StringClass, StringClass)
+ }.get().call("ro.system.build.fingerprint", "none")
+
Class.forName("android.os.SystemProperties")
+ .getDeclaredMethod("get", String::class.java, String::class.java)
+ .apply { isAccessible = true }
+ .invoke(null, "ro.system.build.fingerprint", "none")
+
Integrate
YukiReflection
into your project.
Windows 7 and above / macOS 10.14 and above / Linux distributions (Arch/Debian)
Android Studio 2021.1 and above
IntelliJ IDEA 2021.1 and above
Kotlin 1.7.0 and above
Android Gradle Plugin 7.0 and above
Gradle 7.0 and above
Java 11 and above
Java 17 and above (Since API 1.0.3
)
The project needs to be created using Android Studio
or IntelliJ IDEA
and the type is an Java or Android project and the Kotlin environment dependency has been integrated.
We recommend using Kotlin DSL as the Gradle build script language and SweetDependency to manage dependencies.
Add the repositories and dependencies in your project's SweetDependency
configuration file.
The following example
repositories:
+ # MavenCentral has a 2-hour cache,
+ # if the latest version cannot be integrated, please add this
+ sonatype-oss-releases:
+
+libraries:
+ com.highcapable.yukireflection:
+ api:
+ version: +
+ ...
+
After adding it, run Gradle Sync and all dependencies will be autowired.
Next, deploy dependencies in your project build.gradle.kts
.
The following example
dependencies {
+ implementation(com.highcapable.yukireflection.api)
+ // ...
+}
+
Add repositories in your project build.gradle.kts
or build.gradle
.
Kotlin DSL
repositories {
+ google()
+ mavenCentral()
+ // MavenCentral has a 2-hour cache, if the latest version cannot be integrated, please add this URL
+ maven { url("https://s01.oss.sonatype.org/content/repositories/releases/") }
+}
+
Groovy DSL
repositories {
+ google()
+ mavenCentral()
+ // MavenCentral has a 2-hour cache, if the latest version cannot be integrated, please add this URL
+ maven { url 'https://s01.oss.sonatype.org/content/repositories/releases/' }
+}
+
Add dependencies in your project build.gradle.kts
or build.gradle
.
Kotlin DSL
dependencies {
+ implementation("com.highcapable.yukireflection:api:<yuki-version>")
+ // ...
+}
+
Groovy DSL
dependencies {
+ implementation 'com.highcapable.yukireflection:api:<yuki-version>'
+ // ...
+}
+
Please change <yuki-version> to the latest version here.
Pay Attention
If your project is currently using the 1.x.x version of YukiHookAPI, please do not integrate YukiReflection repeatedly, because YukiHookAPI already includes it functions and there are changes to related functions.
Repeated integration will cause functional conflicts and cause exceptions.
In this case, you should go to the Documentation of YukiHookAPI view the corresponding usage tutorial.
YukiHookAPI will be completely separated from YukiReflection in version 2.0.0, by which time you can use it with YukiHookAPI at the same time.
Modify the Java version of Kotlin in your project build.gradle.kts
or build.gradle
to 17 or above.
Kotlin DSL
android {
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+}
+
Groovy DSL
android {
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = '17'
+ }
+}
+
Notice
Since API 1.0.3, the Java version used by Kotlin defaults to 17, and versions 11 and below are no longer supported.
此文档由 VuePress 强力驱动。
Apache License Version 2.0
+
+Copyright (C) 2019 HighCapable
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
版权所有 © 2019 HighCapable
这里记录了
YukiReflection
的版本更新历史。
特别注意
我们只会对最新的 API 版本进行维护,若你正在使用过时的 API 版本则代表你自愿放弃一切维护的可能性。
MIT
变更为 Apache-2.0
,在此之后的版本将由此许可协议进行分发,您在使用此版本后应变更相关许可协议YukiReflection
isAllowPrintingLogs
debugLog
方法YukiReflection.TAG
YukiReflection.API_VERSION_NAME
YukiReflection.API_VERSION_CODE
YukiReflection.VERSION
remendy
功能,现在可以对其进行分步打印异常HashSet
改为 MutableList
method()
、constructor()
、field()
可直接获取到类中的所有对象功能constructor()
的行为不再是 constructor { emptyParam() }
lazyClass
、lazyClassOrNull
方法,可延迟装载 Class
Member
缓存未生效且持续存储最终引发 APP 内存溢出 (OOM),感谢 Art-ChenMember
的直接缓存功能并作废 YukiReflection.Configs.isEnableMemberCache
Class
的缓存功能Sequence
,优化 Member
的查找速度与性能type
中的错误 Class
对象声明如在使用中有任何问题,或有任何建设性的建议,都可以联系我们。
加入我们的开发者群组。
在 酷安 找到我 @星夜不荟。
感谢您选择并使用 YukiReflection
,如有代码相关的建议和请求,可在 GitHub 提交 Pull Request。
未来是美好的,也是不确定的,让我们共同期待
YukiReflection
在未来的发展空间。
这里收录了
YukiReflection
可能会在后期添加的功能。
使用 stub
的方式创建一个 Kotlin 类,并声明其中的参数,以及其在各个版本中的不同状态。
比如下面的这个 Java 类就是我们需要反射的目标类。
示例如下
package com.example.test;
+
+public class MyClass {
+
+ private String myField = "test";
+
+ public MyClass() {
+ // ...
+ }
+
+ private String myMethod1(String var1, int var2) {
+ // ...
+ }
+
+ private void myMethod2() {
+ // ...
+ }
+
+ private void myMethod3(String var1) {
+ // ...
+ }
+}
+
通过目前 API 的现有用法可以使用如下方式反射调用这个类。
示例如下
classOf<MyClass>().buildOf().current {
+ // 调用 myField
+ val value = field { name = "myField" }.string()
+ // 调用 myMethod1
+ val methodValue = method { name = "myMethod1" }.string("test", 0)
+ // 调用 myMethod2
+ method { name = "myMethod2" }.call()
+ // 调用 myMethod3
+ method { name = "myMethod3" }.call("test")
+}
+
目前要实现的功能是可以使用反射功能直接定义为如下 Kotlin 类。
示例如下
package com.example.test
+
+@ReflectClass
+class MyClass {
+
+ @ReflectField
+ val myField: String = fieldValueOf("none")
+
+ @ReflectMethod
+ fun myMethod1(var1: String, var2: Int): String = methodReturnValueOf("none")
+
+ @ReflectMethod
+ fun myMethod2() = MethodReturnType.Unit
+
+ @ReflectMethod
+ fun myMethod3(var1: String) = MethodReturnType.Unit
+}
+
然后我们就可以直接调用这个定义好的 Kotlin 类来实现反射功能,API 会根据注解自动生成反射代码。
示例如下
MyClass().also {
+ // 调用 myField
+ val value = it.myField
+ // 调用 myMethod1
+ val methodValue = it.myMethod1("test", 0)
+ // 调用 myMethod2
+ it.myMethod2()
+ // 调用 myMethod3
+ it.myMethod3("test")
+}
+
小提示
以上功能可能会在实际推出后有所变化,最终以实际版本的功能为准。
在 Kotlin 中,表示 Java 的类对象的方式是 YourObject::class.java
,这个写法通常会很长,在反射过程中大量使用会很不美观。
在现有版本中,我们内置了常用的 Class
对象,但是这会增大依赖的体积,而且大多数情况下可能都用不到这些对象。
例如 StringClass
、IntType
等等,这些对象都是在 YukiReflection
中内置的。
所以我们计划在后期添加一个功能,可以使用 properties
的方式创建一个需要生成的 Class
对象列表,通过 Gradle 插件依次生成这些 Class
对象。
诸如上面提到的这些原始类型的 Class
对象依然会内置在 YukiReflection
中,其余的 Class
对象需要自行定义。
生成的名称规范为 类名 + Class,为了防止包名冲突,你可以控制生成的 Class
对象的子包名。
在配置文件中,你无需添加 Class
作为后缀。
你可以在 Gradle 插件中定义生成的根包名,默认为 com.highcapable.yukireflection.generated.classes
。
示例如下
# 最基本的定义方式就是直接写名称
+# 将会生成到 com.highcapable.yukireflection.generated.classes.BundleClass
+android.os.Bundle=Bundle
+# 你可以在前方使用 "." 的形式来定义前置子包名
+# 例如我们想把这个类定义到想要的包名
+# 将会生成到 com.highcapable.yukireflection.generated.classes.myandroid.myos.BundleClass
+android.os.Bundle=myandroid.myos.Bundle
+# 你也可以不填写键值内容,这将使用键值名称作为定义的包名和类名
+# 将会生成到 com.highcapable.yukireflection.generated.classes.android.os.BundleClass
+android.os.Bundle
+
上述方式生成的 Class
对象的大概代码形式如下。
package com.highcapable.yukireflection.generated.classes.android.os
+
+// 在默认 ClassLoader 的情况下使用
+val BundleClass: Class<*> = "android.os.Bundle".toClass()
+
+// 在指定 ClassLoader 的情况下使用
+fun BundleClass(loader: ClassLoader): Class<*> = "android.os.Bundle".toClass(loader)
+
也许这个 Class
可能在一些情况下无法被得到,这个时候你可以参考以下配置方式。
示例如下
# 在键值后添加 "?" 的形式来定义可空的 Class 对象
+android.os.Bundle?
+
上述方式生成的 Class
对象的大概代码形式如下。
package com.highcapable.yukireflection.generated.classes.android.os
+
+// 在默认 ClassLoader 的情况下使用
+val BundleClass: Class<*>? = "android.os.Bundle".toClassOrNull()
+
+// 在指定 ClassLoader 的情况下使用
+fun BundleClass(loader: ClassLoader): Class<*>? = "android.os.Bundle".toClassOrNull(loader)
+
如果这个 Class
对象能使用直接调用的方式进行引用,这个时候你可以参考以下配置方式。
示例如下
# 在键值后添加 "!!" 的形式来定义可直接调用的 Class 对象
+android.os.Bundle!!
+
上述方式生成的 Class
对象的大概代码形式如下。
package com.highcapable.yukireflection.generated.classes.android.os
+
+import android.os.Bundle
+
+// 在默认 ClassLoader 的情况下使用
+val BundleClass: Class<Bundle> = classOf<Bundle>()
+
+// 在指定 ClassLoader 的情况下使用
+fun BundleClass(loader: ClassLoader): Class<Bundle> = classOf<Bundle>(loader)
+
有了生成的 Class
对象,我们就可以愉快地使用 YukiReflection
进行反射了。
示例如下
method {
+ name = "onCreate"
+ param(BundleClass)
+}
+
小提示
以上功能可能会在实际推出后有所变化,最终以实际版本的功能为准。
这里包含了
YukiReflection
全部核心功能的用法示例。
这里是 Class 对象自身相关的扩展功能。
假设我们要得到一个不能直接调用的 Class
,通常情况下,我们可以使用标准的反射 API 去查找这个 Class
。
示例如下
// 默认 ClassLoader 环境下的 Class
+var instance = Class.forName("com.demo.Test")
+// 指定 ClassLoader 环境下的 Class
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var instance = customClassLoader?.loadClass("com.demo.Test")
+
这种写法大概不是很友好,此时 YukiReflection
就为你提供了一个可在任意地方使用的语法糖。
以上写法换做 YukiReflection
可写作如下形式。
示例如下
// 直接得到这个 Class
+var instance = "com.demo.Test".toClass()
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var instance = "com.demo.Test".toClass(customClassLoader)
+
如果当前 Class
并不存在,使用上述方法会抛出异常,如果你不确定 Class
是否存在,可以参考下面的解决方案。
示例如下
// 直接得到这个 Class
+// 得不到时结果会为 null 但不会抛出异常
+var instance = "com.demo.Test".toClassOrNull()
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+// 得不到时结果会为 null 但不会抛出异常
+var instance = "com.demo.Test".toClassOrNull(customClassLoader)
+
我们还可以通过映射来得到一个存在的 Class
对象。
示例如下
// 假设这个 Class 是能够被直接得到的
+var instance = classOf<Test>()
+// 我们同样可以自定义 Class 所在的 ClassLoader,这对于 stub 来说非常有效
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var instance = classOf<Test>(customClassLoader)
+
小提示
更多功能请参考 classOf、String.toClass、String.toClassOrNull 方法。
假设我们要得到一个不能直接调用的 Class
,但是我们也不是立刻就需要这个 Class
。
这个时候,你可以使用 lazyClass
来完成这个功能。
示例如下
// 延迟装载这个 Class
+val instance by lazyClass("com.demo.Test")
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+val instance by lazyClass("com.demo.Test") { customClassLoader }
+// 在适当的时候调用这个 Class
+instance.method {
+ // ...
+}
+
如果当前 Class
并不存在,使用上述方法会抛出异常,如果你不确定 Class
是否存在,可以参考下面的解决方案。
示例如下
// 延迟装载这个 Class
+// 得不到时结果会为 null 但不会抛出异常
+val instance by lazyClassOrNull("com.demo.Test")
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+// 得不到时结果会为 null 但不会抛出异常
+val instance by lazyClassOrNull("com.demo.Test") { customClassLoader }
+// 在适当的时候调用这个 Class
+instance?.method {
+ // ...
+}
+
小提示
更多功能请参考 lazyClass、lazyClassOrNull 方法。
假设我们要判断一个 Class
是否存在,通常情况下,我们可以使用标准的反射 API 去查找这个 Class
通过异常来判断是否存在。
示例如下
// 默认 ClassLoader 环境下的 Class
+var isExist = try {
+ Class.forName("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+// 指定 ClassLoader 环境下的 Class
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var isExist = try {
+ customClassLoader?.loadClass("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+
这种写法大概不是很友好,此时 YukiReflection
就为你提供了一个可在任意地方使用的语法糖。
以上写法换做 YukiReflection
可写作如下形式。
示例如下
// 判断这个 Class 是否存在
+var isExist = "com.demo.Test".hasClass()
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var isExist = "com.demo.Test".hasClass(customClassLoader)
+
小提示
更多功能请参考 String.hasClass 方法。
在 R8 等工具混淆后的当前 APP Dex 中的 Class
名称将会难以分辨,且不确定其正确位置,不能直接通过 对象转换 来得到。
此时就有了 DexClassFinder
,它的作用是通过需要查找的 Class
中的字节码特征来确定这个 Class
的实例。
注意
此功能仅适用于 Android 平台。
目前 DexClassFinder 的功能尚在试验阶段,由于仅通过 Java 层实现查找功能,在当前 APP Class 过多时性能可能不能达到最佳水平,如果发生查找不到、定位有误的问题欢迎向我们反馈。
由于是反射层面的 API,目前它只能通过类与成员的特征来定位指定的 Class,不能通过指定字节码中的字符串和方法内容特征来进行定位。
查找 Class 的速度取决于当前设备的性能,目前主流的移动端处理器在 10~15w 数量的 Class 中条件不算复杂的情况下大概在 3~10s 区间,条件稍微复杂的情况下最快速度能达到 25s 以内,匹配到的同类型 Class 越多速度越慢。
特别注意
在 YukiHookAPI 发布 2.0.0 版本后,此功能将被标记为作废,且将会直接从 YukiReflection 中移除。
我们欢迎各位开发者开始使用 DexKit,它是一个使用 C++ 实现的 Dex 高性能运行时解析库,在性能方面比 Java 层更加高效与优秀,目前尚在开发阶段,欢迎提出宝贵建议。
下面是一个简单的用法示例。
假设下面这个 Class
是我们想要得到的,其中的名称经过了混淆,在每个版本可能都不一样。
示例如下
package com.demo;
+
+public class a extends Activity implements Serializable {
+
+ public a(String var1) {
+ // ...
+ }
+
+ private String a;
+
+ private String b;
+
+ private boolean a;
+
+ protected void onCreate(Bundle var1) {
+ // ...
+ }
+
+ private static void a(String var1) {
+ // ...
+ }
+
+ private String a(boolean var1, String var2) {
+ // ...
+ }
+
+ private void a() {
+ // ...
+ }
+
+ public void a(boolean var1, a var2, b var3, String var4) {
+ // ...
+ }
+}
+
此时,我们想得到这个 Class
,可以直接使用 ClassLoader.searchClass
方法。
下方演示的条件中每一个都是可选的,条件越复杂定位越精确,同时性能也会越差。
示例如下
searchClass {
+ // 从指定的包名范围开始查找,实际使用时,你可以同时指定多个包名范围
+ from("com.demo")
+ // 指定当前 Class 的 getSimpleName 的结果,你可以直接对这个字符串进行逻辑判断
+ // 这里我们不确定它的名称是不是 a,可以只判断字符串长度
+ simpleName { it.length == 1 }
+ // 指定继承的父类对象,如果是存在的 stub,可以直接用泛型表示
+ extends<Activity>()
+ // 指定继承的父类对象,可以直接写为完整类名,你还可以同时指定多个
+ extends("android.app.Activity")
+ // 指定实现的接口,如果是存在的 stub,可以直接用泛型表示
+ implements<Serializable>()
+ // 指定实现的接口,可以直接写为完整类名,你还可以同时指定多个
+ implements("java.io.Serializable")
+ // 指定构造方法的类型与样式,以及在当前类中存在的个数 count
+ constructor { param(StringClass) }.count(num = 1)
+ // 指定变量的类型与样式,以及在当前类中存在的个数 count
+ field { type = StringClass }.count(num = 2)
+ // 指定变量的类型与样式,以及在当前类中存在的个数 count
+ field { type = BooleanType }.count(num = 1)
+ // 直接指定所有变量在当前类中存在的个数 count
+ field().count(num = 3)
+ // 如果你认为变量的个数是不确定的,还可以使用如下自定义条件
+ field().count(1..3)
+ field().count { it >= 3 }
+ // 指定方法的类型与样式,以及在当前类中存在的个数 count
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count
+ method {
+ modifiers { isStatic && isPrivate }
+ param(StringClass)
+ returnType = UnitType
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, StringClass)
+ returnType = StringClass
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ emptyParam()
+ returnType = UnitType
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符和模糊类型 VagueType,以及在当前类中存在的个数 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, VagueType, VagueType, StringClass)
+ returnType = UnitType
+ }.count(num = 1)
+ // 直接指定所有方法在当前类中存在的个数 count
+ method().count(num = 5)
+ // 如果你认为方法的个数是不确定的,还可以使用如下自定义条件
+ method().count(1..5)
+ method().count { it >= 5 }
+ // 直接指定所有成员 (Member) 在当前类中存在的个数 count
+ // 成员包括:Field (变量)、Method (方法)、Constructor (构造方法)
+ member().count(num = 9)
+ // 所有成员中一定存在一个 static 修饰符,可以这样加入此条件
+ member {
+ modifiers { isStatic }
+ }
+}.get() // 得到这个 Class 本身的实例,找不到会返回 null
+
小提示
上述用法中对于 Field、Method、Constructor 的条件用法与 Member 扩展 中的相关用法是一致的,仅有小部分区别。
更多功能请参考 MemberRules、FieldRules、MethodRules、ConstructorRules。
默认情况下 DexClassFinder
会使用同步方式查找 Class
,会阻塞当前线程直到找到或找不到发生异常为止,若查找消耗的时间过长,可能会导致当前 APP 发生 ANR 问题。
针对上述问题,我们可以启用异步,只需要加入参数 async = true
,这将不需要你再次启动一个线程,API 已帮你处理好相关问题。
注意
若要使用此功能,你需要在方法参数首位传入当前 APP 的 Context。
对于异步情况下你需要使用 wait 方法来得到结果,get 方法将不再起作用。
示例如下
val context: Context // 假设这就是当前 APP 的 Context
+searchClass(context, async = true) {
+ // ...
+}.wait { class1 ->
+ // 得到异步结果
+}
+searchClass(context, async = true) {
+ // ...
+}.wait { class2 ->
+ // 得到异步结果
+}
+
这样我们的查找过程就是异步运行了,它将不会阻塞主线程,每个查找都将在单独的线程同时进行,可达到并行任务的效果。
由于每次重新打开当前 APP 都会重新进行查找,在当前 APP 版本不变的情况下这是一种重复性能浪费。
此时我们可以通过指定 name
参数来对当前 APP 版本的查找结果进行本地缓存,下一次将直接从本地缓存中读取查找到的类名。
本地缓存使用的是 SharedPreferences
,它将被保存到当前 APP 的数据目录中,在当前 APP 版本更新后会重新进行缓存。
启用本地缓存后,将同时设置 async = true
,你可以不需要再手动进行设置。
注意
若要使用此功能,你需要在方法参数首位传入当前 APP 的 Context。
示例如下
val context: Context // 假设这就是当前 APP 的 Context
+searchClass(context, name = "com.demo.class1") {
+ // ...
+}.wait { class1 ->
+ // 得到异步结果
+}
+searchClass(context, name = "com.demo.class2") {
+ // ...
+}.wait { class2 ->
+ // 得到异步结果
+}
+
如果你想手动清除本地缓存,可以使用如下方法清除当前 APP 版本的缓存。
示例如下
val context: Context // 假设这就是当前 APP 的 Context
+DexClassFinder.clearCache(context)
+
你还可以清除指定版本的 APP 缓存。
示例如下
val context: Context // 假设这就是当前 APP 的 Context
+DexClassFinder.clearCache(context, versionName = "1.0", versionCode = 1)
+
如果你需要使用固定的条件同时查找一组 Class
,那么你只需要使用 all
或 waitAll
方法来得到结果。
// 同步查找,使用 all 得到条件全部查找到的结果
+searchClass {
+ // ...
+}.all().forEach { clazz ->
+ // 得到每个结果
+}
+// 同步查找,使用 all { ... } 遍历每个结果
+searchClass {
+ // ...
+}.all { clazz ->
+ // 得到每个结果
+}
+// 异步查找,使用 waitAll 得到条件全部查找到的结果
+val context: Context // 假设这就是当前 APP 的 Context
+searchClass(context, async = true) {
+ // ...
+}.waitAll { classes ->
+ classes.forEach {
+ // 得到每个结果
+ }
+}
+
小提示
更多功能请参考 ClassLoader.searchClass 方法。
这里是 Class 字节码成员变量 Field、Method、Constructor 相关的扩展功能。
小提示
Member 是 Field、Method、Constructor 的接口描述对象,它在 Java 反射中为 Class 中字节码成员的总称。
假设有一个这样的 Class
。
示例如下
package com.demo;
+
+public class BaseTest {
+
+ public BaseTest() {
+ // ...
+ }
+
+ public BaseTest(boolean isInit) {
+ // ...
+ }
+
+ private void doBaseTask(String taskName) {
+ // ...
+ }
+}
+
package com.demo;
+
+public class Test extends BaseTest {
+
+ public Test() {
+ // ...
+ }
+
+ public Test(boolean isInit) {
+ // ...
+ }
+
+ private static TAG = "Test";
+
+ private BaseTest baseInstance;
+
+ private String a;
+
+ private boolean a;
+
+ private boolean isTaskRunning = false;
+
+ private static void init() {
+ // ...
+ }
+
+ private void doTask(String taskName) {
+ // ...
+ }
+
+ private void release(String taskName, Function<boolean, String> task, boolean isFinish) {
+ // ...
+ }
+
+ private void stop() {
+ // ...
+ }
+
+ private String getName() {
+ // ...
+ }
+
+ private void b() {
+ // ...
+ }
+
+ private void b(String a) {
+ // ...
+ }
+}
+
假设我们要得到 Test
(以下统称“当前 Class
”)的 doTask
方法并执行,通常情况下,我们可以使用标准的反射 API 去查找这个方法。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用反射 API 调用并执行
+Test::class.java
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(instance, "task_name")
+
这种写法大概不是很友好,此时 YukiReflection
就为你提供了一个可在任意地方使用的语法糖。
以上写法换做 YukiReflection
可写作如下形式。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doTask"
+ param(StringClass)
+}.get(instance).call("task_name")
+
小提示
更多功能请参考 MethodFinder。
同样地,我们需要得到 isTaskRunning
变量也可以写作如下形式。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.field {
+ name = "isTaskRunning"
+ type = BooleanType
+}.get(instance).any() // any 为 Field 的任意类型实例化对象
+
小提示
更多功能请参考 FieldFinder。
也许你还想得到当前 Class
的构造方法,同样可以实现。
示例如下
Test::class.java.constructor {
+ param(BooleanType)
+}.get().call(true) // 可创建一个新的实例
+
若想得到的是 Class
的无参构造方法,可写作如下形式。
示例如下
Test::class.java.constructor().get().call() // 可创建一个新的实例
+
小提示
更多功能请参考 ConstructorFinder。
假设我们要得到 Class
中的 getName
方法,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+ returnType = StringClass
+}.get(instance).string() // 得到方法的结果
+
通过观察发现,这个 Class
中只有一个名为 getName
的方法,那我们可不可以再简单一点呢?
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+}.get(instance).string() // 得到方法的结果
+
是的,对于确切不会变化的方法,你可以精简查找条件。
在只使用 get
或 wait
方法得到结果时 YukiReflection
会默认按照字节码顺序匹配第一个查找到的结果。
问题又来了,这个 Class
中有一个 release
方法,但是它的方法参数很长,而且部分类型可能无法直接得到。
通常情况下我们会使用 param(...)
来查找这个方法,但是有没有更简单的方法呢。
此时,在确定方法唯一性后,你可以使用 paramCount
来查找到这个方法。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "release"
+ // 此时我们不必确定方法参数具体类型,写个数就好
+ paramCount = 3
+}.get(instance) // 得到这个方法
+
上述示例虽然能够匹配成功,但是不精确,此时你还可以使用 VagueType
来填充你不想填写的方法参数类型。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "release"
+ // 使用 VagueType 来填充不想填写的类型,同时保证其它类型能够匹配
+ param(StringClass, VagueType, BooleanType)
+}.get(instance) // 得到这个方法
+
如果你并不确定每一个参数的类型,你可以通过 param { ... }
方法来创建一个条件方法体。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "release"
+ // 得到 it (Class) 方法参数类型数组实例来仅判断已知的类型和它的位置
+ param { it[0] == StringClass && it[2] == BooleanType }
+}.get(instance) // 得到这个方法
+
小提示
使用 param { ... } 创建一个条件方法体,其中的变量 it 即当前方法参数的 Class 类型数组实例,此时你就可以自由使用 Class 中的所有对象及其方法。
方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。
更多功能请参考 FieldFinder.type、MethodFinder.param、MethodFinder.returnType、ConstructorFinder.param 方法。
你会注意到 Test
继承于 BaseTest
,现在我们想得到 BaseTest
的 doBaseTask
方法,在不知道父类名称的情况下,要怎么做呢?
参照上面的查找条件,我们只需要在查找条件中加入一个 superClass
即可实现这个功能。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringClass)
+ // 只需要添加这个条件
+ superClass()
+}.get(instance).call("task_name")
+
这个时候我们就可以在父类中取到这个方法了。
superClass
有一个参数为 isOnlySuperClass
,设置为 true
后,可以跳过当前 Class
仅查找当前 Class
的父类。
由于我们现在已知 doBaseTask
方法只存在于父类,可以加上这个条件节省查找时间。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringClass)
+ // 加入一个查找条件
+ superClass(isOnlySuperClass = true)
+}.get(instance).call("task_name")
+
这个时候我们同样可以得到父类中的这个方法。
superClass
一旦设置就会自动循环向后查找全部继承的父类中是否有这个方法,直到查找到目标没有父类(继承关系为 java.lang.Object
)为止。
特别注意
当前查找的 Method 除非指定 superClass 条件,否则只能查找到当前 Class 的 Method,这是 Java 反射 API 的默认行为。
如果我们想查找一个方法名称,但是又不确定它在每个版本中是否发生变化,此时我们就可以使用模糊查找功能。
假设我们要得到 Class
中的 doTask
方法,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name {
+ // 设置名称不区分大小写
+ it.equals("dotask", isIgnoreCase = true)
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
已知当前 Class
中仅有一个 doTask
方法,我们还可以判断方法名称仅包含其中指定的字符。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name {
+ // 仅包含 oTas
+ it.contains("oTas")
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
我们还可以根据首尾字符串进行判断。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name {
+ // 开头包含 do,结尾包含 Task
+ it.startsWith("do") && it.endsWith("Task")
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
通过观察发现这个方法名称中只包含字母,我们还可以再增加一个精确的查找条件。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name {
+ // 开头包含 do,结尾包含 Task,仅包含字母
+ it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters()
+ }
+ param(StringClass)
+}.get(instance).call("task_name")
+
小提示
使用 name { ... } 创建一个条件方法体,其中的变量 it 即当前名称的字符串,此时你就可以在 NameRules 的扩展方法中自由使用其中的功能。
方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。
更多功能请参考 FieldFinder.name、MethodFinder.name 方法以及 NameRules。
有些时候,我们可能需要查找一个 Class
中具有相同特征的一组方法、构造方法、变量,此时,我们就可以利用相对条件匹配来完成。
在查找条件结果的基础上,我们只需要把 get
换为 all
即可得到匹配条件的全部字节码。
假设这次我们要得到 Class
中方法参数个数范围在 1..3
的全部方法,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ paramCount(1..3)
+}.all(instance).forEach { instance ->
+ // 调用执行每个方法
+ instance.call(...)
+}
+
上述示例可完美匹配到如下 3 个方法。
private void doTask(String taskName)
private void release(String taskName, Function<boolean, String> task, boolean isFinish)
private void b(String a)
如果你想更加自由地定义参数个数范围的条件,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ paramCount { it < 3 }
+}.all(instance).forEach { instance ->
+ // 调用执行每个方法
+ instance.call(...)
+}
+
上述示例可完美匹配到如下 6 个方法。
private static void init()
private void doTask(String taskName)
private void stop(String a)
private void getName(String a)
private void b()
private void b(String a)
通过观察 Class
中有两个名称为 b
的方法,可以使用如下实现。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "b"
+}.all(instance).forEach { instance ->
+ // 调用执行每个方法
+ instance.call(...)
+}
+
上述示例可完美匹配到如下 2 个方法。
private void b()
private void b(String a)
小提示
使用 paramCount { ... } 创建一个条件方法体,其中的变量 it 即当前参数个数的整数,此时你就可以在 CountRules 的扩展方法中自由使用其中的功能。
方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。
更多功能请参考 MethodFinder.paramCount、ConstructorFinder.paramCount 方法以及 CountRules。
有些方法和变量在 Class
中是静态的实现,这个时候,我们不需要传入实例就可以调用它们。
假设我们这次要得到静态变量 TAG
的内容。
示例如下
Test::class.java.field {
+ name = "TAG"
+ type = StringClass
+}.get().string() // Field 的类型是字符串,可直接进行 cast
+
假设 Class
中存在同名的非静态 TAG
变量,这个时候怎么办呢?
加入一个筛选条件即可。
示例如下
Test::class.java.field {
+ name = "TAG"
+ type = StringClass
+ // 标识查找的这个变量需要是静态
+ modifiers { isStatic }
+}.get().string() // Field 的类型是字符串,可直接进行 cast
+
我们还可以调用名为 init
的静态方法。
示例如下
Test::class.java.method {
+ name = "init"
+ emptyParam()
+}.get().call()
+
同样地,你可以标识它是一个静态。
示例如下
Test::class.java.method {
+ name = "init"
+ emptyParam()
+ // 标识查找的这个方法需要是静态
+ modifiers { isStatic }
+}.get().call()
+
小提示
使用 modifiers { ... } 创建一个条件方法体,此时你就可以在 ModifierRules 中自由使用其中的功能。
方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。
更多功能请参考 FieldFinder.modifiers、MethodFinder.modifiers、ConstructorFinder.modifiers 方法以及 ModifierRules。
你可能已经注意到了,这里给出的示例 Class
中有两个混淆的变量名称,它们都是 a
,这个时候我们要怎么得到它们呢?
有两种方案。
第一种方案,确定变量的名称和类型。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.field {
+ name = "a"
+ type = BooleanType
+}.get(instance).any() // 得到名称为 a 类型为 Boolean 的变量
+
第二种方案,确定变量的类型所在的位置。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.field {
+ type(BooleanType).index().first()
+}.get(instance).any() // 得到第一个类型为 Boolean 的变量
+
以上两种情况均可得到对应的变量 private boolean a
。
同样地,这个 Class
中也有两个混淆的方法名称,它们都是 b
。
你也可以有两种方案来得到它们。
第一种方案,确定方法的名称和方法参数。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "b"
+ param(StringClass)
+}.get(instance).call("test_string") // 得到名称为 b 方法参数为 [String] 的方法
+
第二种方案,确定方法的参数所在的位置。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ param(StringClass).index().first()
+}.get(instance).call("test_string") // 得到第一个方法参数为 [String] 的方法
+
由于观察到这个方法在 Class
的最后一个,那我们还有一个备选方案。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ order().index().last()
+}.get(instance).call("test_string") // 得到当前 Class 的最后一个方法
+
注意
请尽量避免使用 order 来筛选字节码的下标,它们可能是不确定的,除非你确定它在这个 Class 中的位置一定不会变。
上面介绍的调用字节码的方法都需要使用 get(instance)
才能调用对应的方法,有没有简单一点的办法呢?
此时,你可以在任意实例上使用 current
方法来创建一个调用空间。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ // 执行 doTask 方法
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+ // 执行 stop 方法
+ method {
+ name = "stop"
+ emptyParam()
+ }.call()
+ // 得到 name
+ val name = method { name = "getName" }.string()
+}
+
我们还可以用 superClass
调用当前 Class
父类的方法。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ // 执行父类的 doBaseTask 方法
+ superClass().method {
+ name = "doBaseTask"
+ param(StringClass)
+ }.call("task_name")
+}
+
如果你不喜欢使用一个大括号的调用域来创建当前实例的命名空间,你可以直接使用 current()
方法。
示例如下
// 假设这就是这个 Class 的实例,这个 Class 是不能被直接得到的
+val instance = Test()
+// 执行 doTask 方法
+instance
+ .current()
+ .method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+// 执行 stop 方法
+instance
+ .current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// 得到 name
+val name = instance.current().method { name = "getName" }.string()
+
同样地,它们之间可以连续调用,但不允许内联调用。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+}.current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// 注意,因为 current() 返回的是 CurrentClass 自身对象,所以不能像下面这样调用
+instance.current().current()
+
针对 Field
实例,还有一个便捷的方法,可以直接获取 Field
所在实例的对象。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ // <方案1>
+ field {
+ name = "baseInstance"
+ }.current {
+ method {
+ name = "doBaseTask"
+ param(StringClass)
+ }.call("task_name")
+ }
+ // <方案2>
+ field {
+ name = "baseInstance"
+ }.current()
+ ?.method {
+ name = "doBaseTask"
+ param(StringClass)
+ }?.call("task_name")
+}
+
注意
上述 current 方法相当于帮你调用了 CurrentClass 中的 field { ... }.any()?.current() 方法。
若不存在 CurrentClass 调用域,你需要使用 field { ... }.get(instance).current() 来进行调用。
问题又来了,我想使用反射的方式创建如下的实例并调用其中的方法,该怎么做呢?
示例如下
Test(true).doTask("task_name")
+
通常情况下,我们可以使用标准的反射 API 来调用。
示例如下
"com.demo.Test".toClass()
+ .getDeclaredConstructor(Boolean::class.java)
+ .apply { isAccessible = true }
+ .newInstance(true)
+ .apply {
+ javaClass
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(this, "task_name")
+ }
+
但是感觉这种做法好麻烦,有没有更简洁的调用方法呢?
这个时候,我们还可以借助 buildOf
方法来创建一个实例。
示例如下
"com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.call("task_name")
+}
+
若你希望 buildOf
方法返回当前实例的类型,你可以在其中加入类型泛型声明,而无需使用 as
来 cast
目标类型。
这种情况多用于实例本身的构造方法是私有的,但是里面的方法是公有的,这样我们只需要对其构造方法进行反射创建即可。
示例如下
// 假设这个 Class 是能够直接被得到的
+val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
+test.doTask("task_name")
+
小提示
更多功能请参考 CurrentClass 以及 Class.buildOf 方法。
假设有三个不同版本的 Class
,它们都是这个 APP 不同版本相同的 Class
。
这里面同样都有一个方法 doTask
,假设它们的功能是一样的。
版本 A 示例如下
public class Test {
+
+ public void doTask() {
+ // ...
+ }
+}
+
版本 B 示例如下
public class Test {
+
+ public void doTask(String taskName) {
+ // ...
+ }
+}
+
版本 C 示例如下
public class Test {
+
+ public void doTask(String taskName, int type) {
+ // ...
+ }
+}
+
我们需要在不同的版本中得到这个相同功能的 doTask
方法,要怎么做呢?
此时,你可以使用 RemedyPlan
完成你的需求。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ param(StringClass)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+ method {
+ name = "doTask"
+ param(StringClass, IntType)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+}.wait(instance) {
+ // 得到方法的结果
+}
+
特别注意
使用了 RemedyPlan 的方法查找结果不能再使用 get 的方式得到方法实例,应当使用 wait 方法。
另外,你还可以在使用 多重查找 的情况下继续使用 RemedyPlan
。
示例如下
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiReflection 调用并执行
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+}.waitAll(instance) {
+ // 得到方法的结果
+}
+
假设当前 APP 中不同版本中存在功能相同的 Class
但仅有 Class
的名称不一样。
版本 A 示例如下
public class ATest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
版本 B 示例如下
public class BTest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
这个时候我们想在每个版本都调用这个 Class
里的 doTask
方法该怎么做呢?
通常做法是判断 Class
是否存在。
示例如下
// 首先查找到这个 Class
+val currentClass =
+ if("com.demo.ATest".hasClass()) "com.demo.ATest".toClass() else "com.demo.BTest".toClass()
+// 然后再查找这个方法并调用
+currentClass.method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
感觉这种方案非常的不优雅且繁琐,那么此时 YukiReflection
就为你提供了一个非常方便的 VariousClass
专门来解决这个问题。
现在,你可以直接使用以下方式获取到这个 Class
。
示例如下
VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
若当前 Class
在指定的 ClassLoader
中存在,你可以在 get
中填入你的 ClassLoader
。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
若你不确定所有的 Class
一定会被匹配到,你可以使用 getOrNull
方法。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
+ name = "doTask"
+ emptyParam()
+}?.get()?.call()
+
小提示
更多功能请参考 VariousClass。
在反射过程中,我们可能会遇到泛型问题,在泛型的反射处理上,YukiReflection
同样提供了一个可在任意地方使用的语法糖。
例如我们有如下的泛型类。
示例如下
class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // ...
+ }
+}
+
当我们想在当前 Class
中获得泛型 T
或 R
的 Class
实例,只需要如下实现。
示例如下
class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // 获得当前实例的操作对象
+ // 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写
+ val tClass = current().generic()?.argument()
+ // 获得 R 的 Class 实例,在参数第 1 位
+ val rClass = current().generic()?.argument(index = 1)
+ // 你还可以使用如下写法
+ current().generic {
+ // 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写
+ val tClass = argument()
+ // 获得 R 的 Class 实例,在参数第 1 位
+ val rClass = argument(index = 1)
+ }
+ }
+}
+
当我们想在外部调用这个 Class
时,就可以有如下实现。
示例如下
// 假设这个就是 T 的 Class
+class TI {
+
+ fun foo() {
+ // ...
+ }
+}
+// 假设这个就是 T 的实例
+val tInstance: TI? = ...
+// 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写,并获得其中的方法 foo 并调用
+TestGeneric::class.java.generic()?.argument()?.method {
+ name = "foo"
+ emptyParam()
+}?.get(tInstance)?.invoke<TI>()
+
小提示
更多功能请参考 CurrentClass.generic、Class.generic 方法以及 GenericClass。
这里列举了使用时可能会遇到的误区部分,可供参考。
在查找条件中,除了 order
你只能使用一次 index
功能。
示例如下
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ // 错误的使用方法,请仅保留一个 index 方法
+ returnType(StringClass).index(num = 1)
+}
+
以下查找条件的使用是没有任何问题的。
示例如下
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ order().index(num = 1)
+}
+
在普通方法查找条件中,即使是无参的方法也需要设置查找条件。
假设我们有如下的 Class
。
示例如下
public class TestFoo {
+
+ public void foo(String string) {
+ // ...
+ }
+
+ public void foo() {
+ // ...
+ }
+}
+
我们要得到其中的 public void foo()
方法,可以写作如下形式。
示例如下
TestFoo::class.java.method {
+ name = "foo"
+}
+
但是,上面的例子是错误的。
你会发现这个 Class
中有两个 foo
方法,其中一个带有方法参数。
由于上述例子没有设置 param
的查找条件,得到的结果将会是匹配名称且匹配字节码顺序的第一个方法 public void foo(String string)
,而不是我们需要的最后一个方法。
这是一个经常会出现的错误,没有方法参数就会丢失方法参数查找条件的使用问题。
正确的使用方法如下。
示例如下
TestFoo::class.java.method {
+ name = "foo"
+ // ✅ 正确的使用方法,添加详细的筛选条件
+ emptyParam()
+}
+
至此,上述的示例将可以完美地匹配到 public void foo()
方法。
兼容性说明
在过往历史版本的 API 中是允许匹配不写默认匹配无参方法的做法的,但是最新版本更正了这一问题,请确保你使用的是最新的 API 版本。
在构造方法查找条件中,即使是无参的构造方法也需要设置查找条件。
假设我们有如下的 Class
。
示例如下
public class TestFoo {
+
+ public TestFoo() {
+ // ...
+ }
+}
+
我们要得到其中的 public TestFoo()
构造方法,必须写作如下形式。
示例如下
TestFoo::class.java.constructor { emptyParam() }
+
上面的例子可以成功获取到 public TestFoo()
构造方法。
如果你写作 constructor()
而丢失了 emptyParam()
,此时查找到的结果会是按照字节码顺序排列的的第一位,可能并不是无参的。
兼容性说明
在过往历史版本的 API 中构造方法不填写任何查找参数会直接找不到构造方法,这是一个 BUG,最新版本已经进行修复,请确保你使用的是最新的 API 版本。
API 行为变更
在 1.2.0 及之后的版本中,constructor() 的行为不再是 constructor { emptyParam() } 而是 constructor {},请注意行为变更合理调整查找参数。
在不设置查找条件的情况下,使用 field()
、constructor()
、method()
将返回当前 Class
下的所有成员对象。
使用 get(...)
或 give()
的方式获取将只能得到按照字节码顺序排列的的第一位。
示例如下
Test::class.java.field().get(...)
+Test::class.java.method().give()
+
如果你想得到全部成员对象,你可以使用 all(...)
或 giveAll()
示例如下
Test::class.java.field().all(...)
+Test::class.java.method().giveAll()
+
兼容性说明
在过往历史版本的 API 中,不设置查找条件将抛出异常,此特性在 1.2.0 及之后的版本中加入。
在字节码调用结果中,cast 方法只能指定字节码对应的类型。
例如我们想得到一个 Boolean
类型的变量,把他转换为 String
。
以下是错误的使用方法。
示例如下
field {
+ name = "test"
+ type = BooleanType
+}.get().string() // 错误的使用方法,必须 cast 为字节码目标类型
+
以下是正确的使用方法。
示例如下
field {
+ name = "test"
+ type = BooleanType
+}.get().boolean().toString() // ✅ 正确的使用方法,得到类型后再进行转换
+
在查找方法、变量的时候我们通常需要指定所查找的类型。
示例如下
field {
+ name = "test"
+ type = Boolean::class.javaPrimitiveType
+}
+
在 Kotlin 中表达出 Boolean::class.javaPrimitiveType
这个类型的写法很长,感觉并不方便。
因此,YukiReflection
为开发者封装了常见的类型调用,其中包含了 Android 的相关类型和 Java 的常见类型与原始类型关键字。
这个时候上面的类型就可以写作如下形式了。
示例如下
field {
+ name = "test"
+ type = BooleanType
+}
+
在 Java 常见类型中的原始类型 (或基本类型) 关键字都已被封装为 类型 + Type 的方式,例如 IntType
、FloatType
(它们的字节码类型为 int
、float
)。
相应地,数组类型也有方便的使用方法,假设我们要获得 String[]
类型的数组。
需要写做 java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
才能得到这个类型。
感觉是不是很麻烦,这个时候我们可以使用方法 ArrayClass(StringClass)
来得到这个类型。
同时由于 String
是常见类型,所以还可以直接使用 StringArrayClass
来得到这个类型。
一些常见需求中查找的方法,都有其对应的封装类型以供使用,格式为 类型 + Class。
以下是 Java 中一些特例类型在 YukiReflection
中的封装名称。
void
→ UnitType
java.lang.Void
→ UnitClass
java.lang.Object
→ AnyClass
java.lang.Integer
→ IntClass
java.lang.Character
→ CharClass
注意
以 类型 + Type 封装类型会且仅会表示为 Java 原始类型关键字,由于 Kotlin 中不存在原始类型这个概念,所以它们都会被定义为 KClass。
Java 中共有 9 个原始类型关键字,其中 8 个为原始类型,分别为 boolean、char、byte、short、int、float、long、double,其中 void 类型是一个特例。
同时它们都有 Java 自身对应的封装类型,例如 java.lang.Boolean、java.lang.Integer,这些类型是不相等的,请注意区分。
同样地,数组也有对应的封装类型,它们也需要与 Java 原始类型关键字 进行区分。
例如 byte[] 的封装类型为 ByteArrayType 或 ArrayClass(ByteType),而 Byte[] 的封装类型为 ByteArrayClass 或 ArrayClass(ByteClass),这些类型也是不相等的。
同时,欢迎你能贡献更多的常用类型。
这里的文档将同步最新 API 版本的相关用法,请保持
YukiReflection
为最新版本以使用最新版本的功能。
功能描述主要介绍当前 API 的相关用法和用途。
功能示例主要展示了当前 API 的基本用法示例,可供参考。
首个版本的功能将标记为 v<version>
添加
;
后期新增加的功能将标记为 v<version>
新增
;
后期修改的功能将被追加为 v<version>
修改
;
后期被作废的功能将标记为 v<version>
作废
并会标注删除线;
后期被删除的功能将标记为 v<version>
移除
并会标注删除线。
kt Kotlin Static File
annotation 注解
interface 接口
object 类 (单例)
class 类
field 变量或 get
、set
方法或只读的 get
方法
method 方法
enum Enum 常量
ext-field 扩展的变量 (全局)
ext-method 扩展的方法 (全局)
i-ext-field 扩展的变量 (调用域限制)
i-ext-method 扩展的方法 (调用域限制)
object YukiReflection
+
变更记录
v1.0.0
添加
功能描述
这是
YukiReflection
的装载调用类。
const val TAG: String
+
变更记录
v1.0.3
新增
功能描述
获取当前
YukiReflection
的名称 (标签)。
const val VERSION: String
+
变更记录
v1.0.3
新增
功能描述
获取当前
YukiReflection
的版本。
变更记录
v1.0.0
添加
v1.0.3
作废
不再区分版本名称和版本号,请迁移到 VERSION
变更记录
v1.0.0
添加
v1.0.3
作废
不再区分版本名称和版本号,请迁移到 VERSION
object Configs
+
变更记录
v1.0.0
添加
功能描述
对 API 相关功能的配置类。
inline fun debugLog(initiate: YLog.Configs.() -> Unit)
+
变更记录
v1.0.3
新增
功能描述
配置
YLog.Configs
相关参数。
变更记录
v1.0.0
添加
v1.0.3
作废
请迁移到 debugLog
var isDebug: Boolean
+
变更记录
v1.0.0
添加
功能描述
是否启用 Debug 模式。
默认不启用,启用后将交由日志输出管理器打印详细日志 (例如反射查找功能的耗时) 到控制台。
变更记录
v1.0.0
添加
v1.0.3
作废
请迁移到 debugLog
变更记录
v1.0.0
添加
v1.0.2
作废
Member
的直接缓存功能已被移除,因为其存在内存溢出 (OOM) 问题
inline fun configs(initiate: Configs.() -> Unit)
+
变更记录
v1.0.0
添加
功能描述
对
Configs
类实现了一个 lambda 方法体。
你可以轻松地调用它进行配置。
class CurrentClass internal constructor(private val classSet: Class<*>, internal val instance: Any)
+
变更记录
v1.0.0
添加
功能描述
当前实例的类操作对象。
val name: String
+
变更记录
v1.0.0
添加
功能描述
获得当前
classSet
的Class.getName
。
val simpleName: String
+
变更记录
v1.0.0
添加
功能描述
获得当前
classSet
的Class.getSimpleName
。
fun generic(): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前实例中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前实例中的泛型父类。
如果当前实例不存在泛型将返回 null
。
fun superClass(): SuperClass
+
变更记录
v1.0.0
添加
功能描述
调用父类实例。
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
变更记录
v1.0.0
添加
功能描述
调用当前实例中的变量。
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
变更记录
v1.0.0
添加
功能描述
调用当前实例中的方法。
inner class SuperClass internal constructor(private val superClassSet: Class<*>)
+
变更记录
v1.0.0
添加
功能描述
当前类的父类实例的类操作对象。
val name: String
+
变更记录
v1.0.0
添加
功能描述
获得当前
classSet
中父类的Class.getName
。
val simpleName: String
+
变更记录
v1.0.0
添加
功能描述
获得当前
classSet
中父类的Class.getSimpleName
。
fun generic(): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前实例父类中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前实例父类中的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
变更记录
v1.0.0
添加
功能描述
调用父类实例中的变量。
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
变更记录
v1.0.0
添加
功能描述
调用父类实例中的方法。
class GenericClass internal constructor(private val type: ParameterizedType)
+
变更记录
v1.0.0
添加
功能描述
当前
Class
的泛型父类操作对象。
fun argument(index: Int): Class<*>?
+
inline fun <reified T> argument(index: Int): Class<T>?
+
变更记录
v1.0.0
添加
v1.0.3
修改
方法的返回值可为 null
功能描述
获得泛型参数数组下标的
Class
实例。
注意
在运行时局部变量的泛型会被擦除,获取不到时将会返回 null。
class VariousClass(private vararg val name: String)
+
变更记录
v1.0.0
添加
功能描述
这是一个不确定性
Class
类名装载器,通过name
装载Class
名称数组。
fun get(loader: ClassLoader? = null, initialize: Boolean): Class<*>
+
变更记录
v1.0.0
添加
功能描述
获取匹配的实体类。
使用当前 loader
装载目标 Class
。
fun getOrNull(loader: ClassLoader? = null, initialize: Boolean): Class<*>?
+
变更记录
v1.0.0
添加
功能描述
获取匹配的实体类。
使用当前 loader
装载目标 Class
。
匹配不到 Class
会返回 null
,不会抛出异常。
变更记录
v1.0.0
添加
功能描述
这是自定义
Member
和Class
相关功能的查找匹配以及invoke
的封装类。
open class LazyClass<T> internal constructor(
+ private val instance: Any,
+ private val initialize: Boolean,
+ private val loader: ClassLoaderInitializer?
+)
+
变更记录
v1.0.3
新增
功能描述
懒装载
Class
实例。
fun ClassLoader.listOfClasses(): List<String>
+
变更记录
v1.0.0
添加
功能描述
写出当前
ClassLoader
下所有Class
名称数组。
inline fun ClassLoader.searchClass(context: Context?, name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
变更记录
v1.0.0
添加
功能描述
通过当前
ClassLoader
按指定条件查找并得到 Dex 中的Class
。
特别注意
此方法在 Class 数量过多及查找条件复杂时会非常耗时。
建议启用 async 或设置 name 参数,name 参数将在当前 APP 不同版本中自动进行本地缓存以提升效率。
如果使用了 async 或 name 参数,则必须填写 context 参数。
此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
val Class<*>.hasExtends: Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否有继承关系,父类是Any
将被认为没有继承关系。
infix fun Class<*>?.extends(other: Class<*>?): Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否继承于other
。
如果当前 Class
就是 other
也会返回 true
。
如果当前 Class
为 null
或 other
为 null
会返回 false
。
功能示例
你可以使用此方法来判断两个 Class
是否存在继承关系。
示例如下
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否继承于 B
+if (classA extends classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.notExtends(other: Class<*>?): Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否不继承于other
。
此方法相当于 extends
的反向判断。
功能示例
你可以使用此方法来判断两个 Class
是否不存在继承关系。
示例如下
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否不继承于 B
+if (classA notExtends classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.implements(other: Class<*>?): Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否实现了other
接口类。
如果当前 Class
为 null
或 other
为 null
会返回 false
。
功能示例
你可以使用此方法来判断两个 Class
是否存在依赖关系。
示例如下
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否实现了 B 接口类
+if (classA implements classB) {
+ // Your code here.
+}
+
infix fun Class<*>?.notImplements(other: Class<*>?): Boolean
+
变更记录
v1.0.0
添加
功能描述
当前
Class
是否未实现other
接口类。
此方法相当于 implements
的反向判断。
功能示例
你可以使用此方法来判断两个 Class
是否不存在依赖关系。
示例如下
// 假设下面这两个 Class 就是你需要判断的 Class
+val classA: Class<*>?
+val classB: Class<*>?
+// 判断 A 是否未实现 B 接口类
+if (classA notImplements classB) {
+ // Your code here.
+}
+
fun Class<*>.toJavaPrimitiveType(): Class<*>
+
变更记录
v1.0.0
添加
功能描述
自动转换当前
Class
为 Java 原始类型 (Primitive Type)。
如果当前 Class
为 Java 或 Kotlin 基本类型将自动执行类型转换。
当前能够自动转换的基本类型如下。
kotlin.Unit
java.lang.Void
java.lang.Boolean
java.lang.Integer
java.lang.Float
java.lang.Double
java.lang.Long
java.lang.Short
java.lang.Character
java.lang.Byte
fun String.toClass(loader: ClassLoader?, initialize: Boolean): Class<*>
+
inline fun <reified T> String.toClass(loader: ClassLoader?, initialize: Boolean): Class<T>
+
变更记录
v1.0.0
添加
功能描述
通过字符串类名转换为
loader
中的实体类。
功能示例
你可以直接填写你要查找的目标 Class
,必须在默认 ClassLoader
下存在。
示例如下
"com.example.demo.DemoClass".toClass()
+
你还可以自定义 Class
所在的 ClassLoader
。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
你还可以指定 Class
的目标类型。
示例如下
// 指定的 DemoClass 必须存在或为可访问的 stub
+"com.example.demo.DemoClass".toClass<DemoClass>()
+
你还可以设置在获取到这个 Class
时是否自动执行其默认的静态方法块,默认情况下不会执行。
示例如下
// 获取并执行 DemoClass 默认的静态方法块
+"com.example.demo.DemoClass".toClass(initialize = true)
+
默认的静态方法块在 Java 中使用如下方式定义。
示例如下
public class DemoClass {
+
+ static {
+ // 这里是静态方法块的内容
+ }
+
+ public DemoClass() {
+ // ...
+ }
+}
+
fun String.toClassOrNull(loader: ClassLoader?, initialize: Boolean): Class<*>?
+
inline fun <reified T> String.toClassOrNull(loader: ClassLoader?, initialize: Boolean): Class<T>?
+
变更记录
v1.0.0
添加
功能描述
通过字符串类名转换为
loader
中的实体类。
找不到 Class
会返回 null
,不会抛出异常。
功能示例
用法请参考 String.toClass 方法。
inline fun <reified T> classOf(loader: ClassLoader?, initialize: Boolean): Class<T>
+
变更记录
v1.0.0
添加
功能描述
通过
T
得到其Class
实例并转换为实体类。
功能示例
我们要获取一个 Class
在 Kotlin 下不通过反射时应该这样做。
示例如下
DemoClass::class.java
+
现在,你可以直接 cast
一个实例并获取它的 Class
对象,必须在当前 ClassLoader
下存在。
示例如下
classOf<DemoClass>()
+
若目标存在的 Class
为 stub
,通过这种方式,你还可以自定义 Class
所在的 ClassLoader
。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+classOf<DemoClass>(customClassLoader)
+
fun lazyClass(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<Any>
+
inline fun <reified T> lazyClass(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<T>
+
fun lazyClass(variousClass: VariousClass, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.NonNull<Any>
+
变更记录
v1.0.3
新增
功能描述
懒装载
Class
。
fun lazyClassOrNull(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<Any>
+
inline fun <reified T> lazyClassOrNull(name: String, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<T>
+
fun lazyClassOrNull(variousClass: VariousClass, initialize: Boolean, loader: ClassLoaderInitializer?): LazyClass.Nullable<Any>
+
变更记录
v1.0.3
新增
功能描述
懒装载
Class
。
fun String.hasClass(loader: ClassLoader?): Boolean
+
变更记录
v1.0.0
添加
功能描述
通过字符串类名使用指定的
ClassLoader
查找是否存在。
功能示例
你可以轻松的使用此方法判断字符串中的类是否存在,效果等同于直接使用 Class.forName
。
示例如下
if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
填入方法中的 loader
参数可判断指定的 ClassLoader
中的 Class
是否存在。
示例如下
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找变量是否存在。
inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找方法是否存在。
inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找构造方法是否存在。
inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找
Member
中匹配的描述符。
inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
+
变更记录
v1.0.0
添加
功能描述
查找
Class
中匹配的描述符。
inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
+
变更记录
v1.0.0
添加
功能描述
查找并得到变量。
inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
+
变更记录
v1.0.0
添加
功能描述
查找并得到方法。
inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
变更记录
v1.0.0
添加
功能描述
查找并得到构造方法。
fun Class<*>.generic(): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前
Class
的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
+
变更记录
v1.0.0
添加
功能描述
获得当前
Class
的泛型父类。
如果当前实例不存在泛型将返回 null
。
inline fun <reified T : Any> T.current(ignored: Boolean): CurrentClass
+
inline fun <reified T : Any> T.current(ignored: Boolean, initiate: CurrentClass.() -> Unit): T
+
变更记录
v1.0.0
添加
功能描述
获得当前实例的类操作对象。
inline fun Class<*>.buildOf(vararg args: Any?, initiate: ConstructorConditions): Any?
+
inline fun <T> Class<*>.buildOf(vararg args: Any?, initiate: ConstructorConditions): T?
+
变更记录
v1.0.0
添加
功能描述
通过构造方法创建新实例,指定类型
T
或任意类型Any
。
inline fun Class<*>.allMethods(isAccessible: Boolean, result: (index: Int, method: Method) -> Unit)
+
变更记录
v1.0.0
添加
功能描述
遍历当前类中的所有方法。
inline fun Class<*>.allConstructors(isAccessible: Boolean, result: (index: Int, constructor: Constructor<*>) -> Unit)
+
变更记录
v1.0.0
添加
功能描述
遍历当前类中的所有构造方法。
inline fun Class<*>.allFields(isAccessible: Boolean, result: (index: Int, field: Field) -> Unit)
+
变更记录
v1.0.0
添加
功能描述
遍历当前类中的所有变量。
abstract class BaseFinder
+
变更记录
v1.0.0
添加
功能描述
这是
Class
与Member
查找类功能的基本类实现。
inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
+
变更记录
v1.0.0
添加
功能描述
字节码下标筛选实现类。
fun index(num: Int)
+
变更记录
v1.0.0
添加
功能描述
设置下标。
若 index
小于零则为倒序,此时可以使用 IndexTypeConditionSort.reverse
方法实现。
可使用 IndexTypeConditionSort.first
和 IndexTypeConditionSort.last
设置首位和末位筛选条件。
fun index(): IndexTypeConditionSort
+
变更记录
v1.0.0
添加
功能描述
得到下标。
inner class IndexTypeConditionSort internal constructor()
+
变更记录
v1.0.0
添加
功能描述
字节码下标排序实现类。
fun first()
+
变更记录
v1.0.0
添加
功能描述
设置满足条件的第一个。
fun last()
+
变更记录
v1.0.0
添加
功能描述
设置满足条件的最后一个。
fun reverse(num: Int)
+
变更记录
v1.0.0
添加
功能描述
设置倒序下标。
class CountRules private constructor()
+
变更记录
v1.0.0
添加
功能描述
这是一个模糊
Class
、Member
数组 (下标) 个数条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
fun Int.isZero(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否为 0。
fun Int.moreThan(count: Int): Boolean
+
变更记录
v1.0.0
添加
功能描述
大于
count
。
fun Int.lessThan(count: Int): Boolean
+
变更记录
v1.0.0
添加
功能描述
小于
count
。
fun Int.inInterval(countRange: IntRange): Boolean
+
变更记录
v1.0.0
添加
功能描述
在
countRange
区间 A ≤ this ≤ B。
class ModifierRules private constructor()
+
变更记录
v1.0.0
添加
功能描述
这是一个
Class
、Member
描述符条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
val isPublic: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含public
。
val isPrivate: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含private
。
val isProtected: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含protected
。
val isStatic: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含static
。
对于任意的静态 Class
、Member
可添加此描述进行确定。
注意
Kotlin → Jvm 后的 object 类中的方法并不是静态的。
val isFinal: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含final
。
注意
Kotlin → Jvm 后没有 open 符号标识的 Class、Member 和没有任何关联的 Class、Member 都将为 final。
val isSynchronized: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含synchronized
。
val isVolatile: Boolean
+
变更记录
v1.0.0
添加
功能描述
Field
类型是否包含volatile
。
val isTransient: Boolean
+
变更记录
v1.0.0
添加
功能描述
Field
类型是否包含transient
。
val isNative: Boolean
+
变更记录
v1.0.0
添加
功能描述
Method
类型是否包含native
。
对于任意 JNI 对接的 Method
可添加此描述进行确定。
val isInterface: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
类型是否包含interface
。
val isAbstract: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含abstract
。
对于任意的抽象 Class
、Member
可添加此描述进行确定。
val isStrict: Boolean
+
变更记录
v1.0.0
添加
功能描述
Class
、Member
类型是否包含strictfp
。
class NameRules private constructor()
+
变更记录
v1.0.0
添加
功能描述
这是一个模糊
Class
、Member
名称条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
fun String.isSynthetic(index: Int): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否为匿名类的主类调用对象。
fun String.isOnlySymbols(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有符号。
fun String.isOnlyLetters(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有字母。
fun String.isOnlyNumbers(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有数字。
fun String.isOnlyLettersNumbers(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有字母或数字。
fun String.isOnlyLowercase(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有小写字母。
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
fun String.isOnlyUppercase(): Boolean
+
变更记录
v1.0.0
添加
功能描述
是否只有大写字母。
在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。
class ObjectRules private constructor(private val instance: Any)
+
变更记录
v1.0.0
添加
功能描述
这是一个任意对象条件实现类。
可对 R8 混淆后的 Class
、Member
进行更加详细的定位。
class DexClassFinder internal constructor(
+ private val context: Context?,
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder
+
变更记录
v1.0.0
添加
功能描述
Class
查找类。
可使用 BaseDexClassLoader
通过指定条件查找指定 Class
或一组 Class
。
注意
此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。
变更记录
v1.0.0
添加
fun clearCache(context: Context, versionName: String?, versionCode: Long?)
+
变更记录
v1.0.0
添加
功能描述
清除当前
DexClassFinder
的Class
缓存。
适用于全部通过 ClassLoader.searchClass 获取的 DexClassFinder
。
var fullName: String
+
变更记录
v1.0.0
添加
功能描述
设置
Class
完整名称。
只会查找匹配到的 Class.getName
。
例如 com.demo.Test
需要填写 com.demo.Test
。
var simpleName: String
+
变更记录
v1.0.0
添加
功能描述
设置
Class
简单名称。
只会查找匹配到的 Class.getSimpleName
。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
会为空,此时你可以使用 singleName。
var singleName: String
+
变更记录
v1.0.0
添加
功能描述
设置
Class
独立名称。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。
fun from(vararg name: String): FromPackageRules
+
变更记录
v1.0.0
添加
功能描述
设置在指定包名范围查找当前
Class
。
设置后仅会在当前 name
开头匹配的包名路径下进行查找,可提升查找速度。
例如 ↓
com.demo.test
com.demo.test.demo
注意
建议设置此参数指定查找范围,否则 Class 过多时将会非常慢。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
标识符筛选条件。
可不设置筛选条件。
fun fullName(value: String): ClassNameRules
+
变更记录
v1.0.0
添加
功能描述
设置
Class
完整名称。
只会查找匹配到的 Class.getName
。
例如 com.demo.Test
需要填写 com.demo.Test
。
fun simpleName(value: String): ClassNameRules
+
变更记录
v1.0.0
添加
功能描述
设置
Class
简单名称。
只会查找匹配到的 Class.getSimpleName
。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest 会为空
,此时你可以使用 singleName。
fun singleName(value: String): ClassNameRules
+
变更记录
v1.0.0
添加
功能描述
设置
Class
独立名称。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
例如 com.demo.Test
只需要填写 Test
。
对于匿名类例如 com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。
fun fullName(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
完整名称条件。
只会查找匹配到的 Class.getName
。
fun simpleName(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
简单名称条件。
只会查找匹配到的 Class.getSimpleName
。
fun singleName(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
独立名称条件。
设置后将首先使用 Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。
inline fun <reified T> extends()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
继承的父类。
fun extends(vararg name: String)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
继承的父类。
会同时查找 name
中所有匹配的父类。
inline fun <reified T> implements()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
实现的接口类。
fun implements(vararg name: String)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
实现的接口类。
会同时查找 name
中所有匹配的接口类。
fun anonymous()
+
变更记录
v1.0.0
添加
功能描述
标识
Class
为匿名类。
例如 com.demo.Test$1
或 com.demo.Test$InnerTest
。
标识后你可以使用 enclosing 来进一步指定匿名类的 (封闭类) 主类。
fun noExtends()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
没有任何继承。
此时 Class
只应该继承于 Any
。
注意
设置此条件后 extends 将失效。
fun noImplements()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
没有任何接口。
注意
设置此条件后 implements 将失效。
fun noSuper()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
没有任何继承与接口。
此时 Class
只应该继承于 Any
。
注意
设置此条件后 extends 与 implements 将失效。
inline fun <reified T> enclosing()
+
变更记录
v1.0.0
添加
功能描述
设置
Class
匿名类的 (封闭类) 主类。
fun enclosing(vararg name: String)
+
变更记录
v1.0.0
添加
功能描述
设置
Class
匿名类的 (封闭类) 主类。
会同时查找 name
中所有匹配的 (封闭类) 主类。
inner class FromPackageRules internal constructor(private val packages: MutableList<ClassRulesData.PackageRulesData>)
+
变更记录
v1.0.0
添加
功能描述
包名范围名称过滤匹配条件实现类。
fun absolute()
+
变更记录
v1.0.0
添加
功能描述
设置包名绝对匹配。
例如有如下包名 ↓
com.demo.test.a
com.demo.test.a.b
com.demo.test.active
若包名条件为 com.demo.test.a
则绝对匹配仅能匹配到第一个。
相反地,不设置以上示例会全部匹配。
inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
+
变更记录
v1.0.0
添加
功能描述
类名匹配条件实现类。
fun optional()
+
变更记录
v1.0.0
添加
功能描述
设置类名可选。
例如有如下类名 ↓
com.demo.Test
fullName / Test
simpleName
defpackage.a
fullName / a
simpleName
这两个类名都是同一个类,但是在有些版本中被混淆有些版本没有。
此时可设置类名为 com.demo.Test
fullName / Test
simpleName。
这样就可在完全匹配类名情况下使用类名而忽略其它查找条件,否则忽略此条件继续使用其它查找条件。
inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置
Class
满足的Member
条件。
inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置
Class
满足的Field
条件。
inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置
Class
满足的Method
条件。
inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置
Class
满足的Constructor
条件。
inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
+
变更记录
v1.0.0
添加
功能描述
Class
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建监听结果事件方法体。
fun get(): Class<*>?
+
变更记录
v1.0.0
添加
功能描述
得到
Class
本身。
若有多个 Class
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
若你设置了 async
请使用 wait 方法。
fun all(): MutableList<Class<*>>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
功能描述
得到
Class
本身数组。
返回全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
若你设置了 async
请使用 waitAll 方法。
fun all(result: (Class<*>) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
得到
Class
本身数组 (依次遍历)。
回调全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将不会执行。
若你设置了 async
请使用 waitAll 方法。
fun wait(result: (Class<*>?) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
得到
Class
本身 (异步)。
若有多个 Class
结果只会回调第一个。
在查找条件找不到任何结果的时候将回调 null。
你需要设置 async
后此方法才会被回调,否则请使用 get 方法。
fun waitAll(result: (MutableList<Class<*>>) -> Unit): Result
+
变更记录
v1.0.0
添加
v1.0.3
修改
result
类型由 HashSet
修改为 MutableList
功能描述
得到
Class
本身数组 (异步)。
回调全部查找条件匹配的多个 Class
实例。
在查找条件找不到任何结果的时候将回调空的 MutableList
。
你需要设置 async
后此方法才会被回调,否则请使用 all 方法。
fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
监听找不到
Class
时。
fun ignored(): Result
+
变更记录
v1.0.0
添加
功能描述
忽略异常并停止打印任何错误日志。
此时若要监听异常结果,你需要手动实现 onNoClassDefFoundError 方法。
class ConstructorRules internal constructor(private val rulesData: ConstructorRulesData) : BaseRules
+
变更记录
v1.0.0
添加
功能描述
Constructor
查找条件实现类。
var paramCount: Int
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
标识符筛选条件。
可不设置筛选条件。
fun emptyParam()
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
空参数、无参数。
fun param(vararg paramType: Any)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。
特别注意
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
fun param(conditions: ObjectsConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数条件。
特别注意
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
fun paramCount(numRange: IntRange)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
fun paramCount(conditions: CountConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
class FieldRules internal constructor(private val rulesData: FieldRulesData) : BaseRules
+
变更记录
v1.0.0
添加
功能描述
Field
查找条件实现类。
var name: String
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称。
var type: Any?
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型。
可不填写类型。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Field
标识符筛选条件。
可不设置筛选条件。
fun name(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称条件。
fun type(conditions: ObjectConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型条件。
可不填写类型。
class MemberRules internal constructor(private val rulesData: MemberRulesData) : BaseRules
+
变更记录
v1.0.0
添加
功能描述
Member
查找条件实现类。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Member
标识符筛选条件。
可不设置筛选条件。
class MethodRules internal constructor(private val rulesData: MethodRulesData) : BaseRules
+
变更记录
v1.0.0
添加
功能描述
Method
查找条件实现类。
var name: String
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称。
var paramCount: Int
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
var returnType: Any?
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值。
可不填写返回值。
fun modifiers(conditions: ModifierConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
标识符筛选条件。
可不设置筛选条件。
fun emptyParam()
+
变更记录
v1.0.0
添加
功能描述
设置
Method
空参数、无参数。
fun param(vararg paramType: Any)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Method
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。
特别注意
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
fun param(conditions: ObjectsConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数条件。
特别注意
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
fun name(conditions: NameConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称条件。
fun paramCount(numRange: IntRange)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
fun paramCount(conditions: CountConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
fun returnType(conditions: ObjectConditions)
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值条件。
可不填写返回值。
class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
+
变更记录
v1.0.0
添加
功能描述
当前
Member
查找条件结果实现类。
fun none(): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置当前
Member
在查找条件中个数为0
。
fun count(num: Int): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置当前
Member
在查找条件中需要全部匹配的个数。
fun count(numRange: IntRange): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置当前
Member
在查找条件中需要全部匹配的个数范围。
fun count(conditions: CountConditions): MemberRulesResult
+
变更记录
v1.0.0
添加
功能描述
设置当前
Member
在查找条件中需要全部匹配的个数条件。
class ConstructorFinder internal constructor(override val classSet: Class<*>) : MemberBaseFinder
+
变更记录
v1.0.0
添加
功能描述
Constructor
查找类。
可通过指定类型查找指定 Constructor
或一组 Constructor
。
var paramCount: Int
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
标识符筛选条件。
可不设置筛选条件,默认模糊查找并取第一个匹配的 Constructor
。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun emptyParam(): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
空参数、无参数。
fun param(vararg paramType: Any): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。
特别注意
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun param(conditions: ObjectsConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数条件。
特别注意
无参 Constructor 请使用 emptyParam 设置查找条件。
有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(num: Int): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数。
若参数个数小于零则忽略并使用 param
。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(numRange: IntRange): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Constructor
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
变更记录
v1.0.0
添加
功能描述
设置在
classSet
的所有父类中查找当前Constructor
。
注意
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
变更记录
v1.0.0
添加
功能描述
Constructor
重查找实现类,可累计失败次数直到查找成功。
inline fun constructor(initiate: ConstructorConditions)
+
变更记录
v1.0.0
添加
功能描述
创建需要重新查找的
Constructor
。
你可以添加多个备选 Constructor
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
变更记录
v1.0.0
添加
功能描述
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Constructor<*>>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 HashSet
修改为 MutableList
功能描述
当在
RemedyPlan
中找到结果时。
功能示例
你可以方便地对重查找的 Constructor
实现 onFind
方法。
示例如下
constructor {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
变更记录
v1.0.0
添加
功能描述
Constructor
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建监听结果事件方法体。
功能示例
你可以使用 lambda 形式创建 Result
类。
示例如下
constructor {
+ // Your code here.
+}.result {
+ get().call()
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
fun get(): Instance
+
变更记录
v1.0.0
添加
功能描述
获得
Constructor
实例处理类。
若有多个 Constructor
结果只会返回第一个。
特别注意
若你设置了 remedys 请使用 wait 回调结果方法。
功能示例
你可以通过获得方法所在实例来执行构造方法创建新的实例对象。
示例如下
constructor {
+ // Your code here.
+}.get().call()
+
你可以 cast
构造方法为指定类型的实例对象。
示例如下
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>()
+
特别注意
若构造方法含有参数则后方参数必填。
示例如下
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>("param1", "param2")
+
fun all(): MutableList<Instance>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 ArrayList
修改为 MutableList
功能描述
获得
Constructor
实例处理类数组。
返回全部查找条件匹配的多个 Constructor
实例结果。
功能示例
你可以通过此方法来获得当前条件结果中匹配的全部 Constructor
。
示例如下
constructor {
+ // Your code here.
+}.all().forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Constructor<*>?
+
变更记录
v1.0.0
添加
功能描述
得到
Constructor
本身。
若有多个 Constructor
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Constructor<*>>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
功能描述
得到
Constructor
本身数组。
返回全部查找条件匹配的多个 Constructor
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(initiate: Instance.() -> Unit)
+
变更记录
v1.0.0
添加
功能描述
获得
Constructor
实例处理类,配合RemedyPlan
使用。
若有多个 Constructor
结果只会返回第一个。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(initiate: MutableList<Instance>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 ArrayList
修改为 MutableList
功能描述
获得
Constructor
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Constructor
实例结果。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建
Constructor
重查找功能。
功能示例
当你遇到一种 Constructor
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchConstructor
捕获异常二次查找 Constructor
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
示例如下
constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
监听找不到
Constructor
时。
只会返回第一次的错误信息,不会返回 RemedyPlan
的错误信息。
fun ignored(): Result
+
变更记录
v1.0.0
添加
功能描述
忽略异常并停止打印任何错误日志。
注意
此时若要监听异常结果,你需要手动实现 onNoSuchConstructor 方法。
inner class Instance internal constructor(private val constructor: Constructor<*>?)
+
变更记录
v1.0.0
添加
功能描述
Constructor
实例处理类。
fun call(vararg args: Any?): Any?
+
变更记录
v1.0.0
添加
功能描述
执行
Constructor
创建目标实例,不指定目标实例类型。
fun <T> newInstance(vararg args: Any?): T?
+
变更记录
v1.0.0
添加
功能描述
执行
Constructor
创建目标实例 ,指定T
目标实例类型。
class FieldFinder internal constructor(override val classSet: Class<*>?) : MemberBaseFinder
+
变更记录
v1.0.0
添加
功能描述
Field
查找类。
可通过指定类型查找指定 Field
或一组 Field
。
var name: String
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称。
特别注意
若不填写名称则必须存在一个其它条件。
var type: Any?
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型。
可不填写类型。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
标识符筛选条件。
可不设置筛选条件。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun order(): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
顺序筛选字节码的下标。
fun name(value: String): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称。
特别注意
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun name(conditions: NameConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
名称条件。
特别注意
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun type(value: Any): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型。
可不填写类型。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun type(conditions: ObjectConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Field
类型条件。
可不填写类型。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
变更记录
v1.0.0
添加
功能描述
设置在
classSet
的所有父类中查找当前Field
。
注意
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
变更记录
v1.0.0
添加
功能描述
Field
重查找实现类,可累计失败次数直到查找成功。
inline fun field(initiate: FieldConditions): Result
+
变更记录
v1.0.0
添加
功能描述
创建需要重新查找的
Field
。
你可以添加多个备选 Field
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
变更记录
v1.0.0
添加
功能描述
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Field>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 HashSet
修改为 MutableList
功能描述
当在
RemedyPlan
中找到结果时。
功能示例
你可以方便地对重查找的 Field
实现 onFind
方法。
示例如下
field {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
变更记录
v1.0.0
添加
功能描述
Field
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建监听结果事件方法体。
功能示例
你可以使用 lambda 形式创建 Result
类。
示例如下
field {
+ // Your code here.
+}.result {
+ get(instance).set("something")
+ get(instance).string()
+ get(instance).cast<CustomClass>()
+ get().boolean()
+ all(instance)
+ give()
+ giveAll()
+ onNoSuchField {}
+}
+
fun get(instance: Any?): Instance
+
变更记录
v1.0.0
添加
功能描述
获得
Field
实例处理类。
若有多个 Field
结果只会返回第一个。
功能示例
你可以轻松地得到 Field
的实例以及使用它进行设置实例。
示例如下
field {
+ // Your code here.
+}.get(instance).set("something")
+
如果你取到的是静态 Field
,可以不需要设置实例。
示例如下
field {
+ // Your code here.
+}.get().set("something")
+
fun all(instance: Any?): MutableList<Instance>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 ArrayList
修改为 MutableList
功能描述
获得
Field
实例处理类数组。
返回全部查找条件匹配的多个 Field
实例结果。
功能示例
你可以通过此方法来获得当前条件结果中匹配的全部 Field
,其 Field
所在实例用法与 get
相同。
示例如下
field {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.self
+}
+
fun give(): Field?
+
变更记录
v1.0.0
添加
功能描述
得到
Field
本身。
若有多个 Field 结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Field>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
功能描述
得到
Field
本身数组。
返回全部查找条件匹配的多个 Field
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
变更记录
v1.0.0
添加
功能描述
获得
Field
实例处理类,配合RemedyPlan
使用。
若有多个 Field
结果只会返回第一个。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(instance: Any?, initiate: MutableList<Instance>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 ArrayList
修改为 MutableList
功能描述
获得
Field
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Field
实例结果。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建
Field
重查找功能。
功能示例
当你遇到一种 Field
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchField
捕获异常二次查找 Field
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
示例如下
field {
+ // Your code here.
+}.remedys {
+ field {
+ // Your code here.
+ }
+ field {
+ // Your code here.
+ }
+}
+
fun onNoSuchField(result: (Throwable) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
监听找不到
Field
时。
fun ignored(): Result
+
变更记录
v1.0.0
添加
功能描述
忽略异常并停止打印任何错误日志。
注意
此时若要监听异常结果,你需要手动实现 onNoSuchField 方法。
inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
+
变更记录
v1.0.0
添加
功能描述
Field
实例变量处理类。
fun current(ignored: Boolean): CurrentClass?
+
inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
+
变更记录
v1.0.0
添加
功能描述
获得当前
Field
自身self
实例的类操作对象CurrentClass
。
fun <T> cast(): T?
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
实例。
fun byte(): Byte?
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Byte 实例。
fun int(): Int
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Int 实例。
fun long(): Long
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Long 实例。
fun short(): Short
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Short 实例。
fun double(): Double
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Double 实例。
fun float(): Float
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Float 实例。
fun string(): String
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
String 实例。
fun char(): Char
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Char 实例。
fun boolean(): Boolean
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Boolean 实例。
fun any(): Any?
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Any 实例。
inline fun <reified T> array(): Array<T>
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
Array 实例。
inline fun <reified T> list(): List<T>
+
变更记录
v1.0.0
添加
功能描述
得到当前
Field
List 实例。
fun set(any: Any?)
+
变更记录
v1.0.0
添加
功能描述
设置当前
Field
实例。
fun setTrue()
+
变更记录
v1.0.0
添加
功能描述
设置当前
Field
实例为true
。
特别注意
请确保实例对象类型为 Boolean。
fun setFalse()
+
变更记录
v1.0.0
添加
功能描述
设置当前
Field
实例为false
。
特别注意
请确保实例对象类型为 Boolean。
fun setNull()
+
变更记录
v1.0.0
添加
功能描述
设置当前
Field
实例为null
。
class MethodFinder internal constructor(override val classSet: Class<*>) : MemberBaseFinder
+
变更记录
v1.0.0
添加
功能描述
Method
查找类。
可通过指定类型查找指定 Method
或一组 Method
。
var name: String
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称。
特别注意
若不填写名称则必须存在一个其它条件。
var paramCount: Int
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此变量指定参数个数。
若参数个数小于零则忽略并使用 param
。
var returnType: Any?
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值,可不填写返回值。
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
标识符筛选条件。
可不设置筛选条件。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun emptyParam(): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
空参数、无参数。
fun param(vararg paramType: Any): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数。
如果同时使用了 paramCount
则 paramType
的数量必须与 paramCount
完全匹配。
如果 Method
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。
特别注意
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun param(conditions: ObjectsConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数条件。
特别注意
无参 Method 请使用 emptyParam 设置查找条件。
有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun order(): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
顺序筛选字节码的下标。
fun name(value: String): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称。
特别注意
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun name(conditions: NameConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
名称条件。
特别注意
若不填写名称则必须存在一个其它条件。
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(num: Int): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数。
若参数个数小于零则忽略并使用 param
。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(numRange: IntRange): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数范围。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数范围。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
参数个数条件。
你可以不使用 param
指定参数类型而是仅使用此方法指定参数个数条件。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun returnType(value: Any): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值。
可不填写返回值。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun returnType(conditions: ObjectConditions): IndexTypeCondition
+
变更记录
v1.0.0
添加
功能描述
设置
Method
返回值条件。
可不填写返回值。
特别注意
存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。
fun superClass(isOnlySuperClass: Boolean)
+
变更记录
v1.0.0
添加
功能描述
设置在
classSet
的所有父类中查找当前Method
。
注意
若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。
inner class RemedyPlan internal constructor()
+
变更记录
v1.0.0
添加
功能描述
Method
重查找实现类,可累计失败次数直到查找成功。
inline fun method(initiate: MethodConditions): Result
+
变更记录
v1.0.0
添加
功能描述
创建需要重新查找的
Method
。
你可以添加多个备选 Method
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。
inner class Result internal constructor()
+
变更记录
v1.0.0
添加
功能描述
RemedyPlan
结果实现类。
fun onFind(initiate: MutableList<Method>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 HashSet
修改为 MutableList
功能描述
当在
RemedyPlan
中找到结果时。
功能示例
你可以方便地对重查找的 Method
实现 onFind
方法。
示例如下
method {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
变更记录
v1.0.0
添加
功能描述
Method
查找结果实现类。
inline fun result(initiate: Result.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建监听结果事件方法体。
功能示例
你可以使用 lambda 形式创建 Result
类。
示例如下
method {
+ // Your code here.
+}.result {
+ get(instance).call()
+ all(instance)
+ remedys {}
+ onNoSuchMethod {}
+}
+
fun get(instance: Any?): Instance
+
变更记录
v1.0.0
添加
功能描述
获得
Method
实例处理类。
若有多个 Method
结果只会返回第一个。
特别注意
若你设置了 remedys 请使用 wait 回调结果方法。
功能示例
你可以通过获得方法所在实例来执行 Method
。
示例如下
method {
+ // Your code here.
+}.get(instance).call()
+
若当前为静态方法,你可以不设置实例。
示例如下
method {
+ // Your code here.
+}.get().call()
+
fun all(instance: Any?): MutableList<Instance>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 ArrayList
修改为 MutableList
功能描述
获得
Method
实例处理类数组。
返回全部查找条件匹配的多个 Method
实例结果。
功能示例
你可以通过此方法来获得当前条件结果中匹配的全部 Method
,其方法所在实例用法与 get
相同。
示例如下
method {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Method?
+
变更记录
v1.0.0
添加
功能描述
得到
Method
本身。
若有多个 Method
结果只会返回第一个。
在查找条件找不到任何结果的时候将返回 null
。
fun giveAll(): MutableList<Method>
+
变更记录
v1.0.0
添加
v1.0.3
修改
返回值类型由 HashSet
修改为 MutableList
功能描述
得到
Method
本身数组。
返回全部查找条件匹配的多个 Method
实例。
在查找条件找不到任何结果的时候将返回空的 MutableList
。
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
变更记录
v1.0.0
添加
功能描述
获得
Method
实例处理类,配合RemedyPlan
使用。
若有多个 Method
结果只会返回第一个。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
fun waitAll(instance: Any?, initiate: MutableList<Instance>.() -> Unit)
+
变更记录
v1.0.0
添加
v1.0.3
修改
initiate
类型由 ArrayList
修改为 MutableList
功能描述
获得
Method
实例处理类数组,配合RemedyPlan
使用。
返回全部查找条件匹配的多个 Method
实例结果。
特别注意
若你设置了 remedys 必须使用此方法才能获得结果。
若你没有设置 remedys 此方法将不会被回调。
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
创建
Method
重查找功能。
功能示例
当你遇到一种 Method
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchMethod
捕获异常二次查找 Method
。
若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。
示例如下
method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
变更记录
v1.0.0
添加
功能描述
监听找不到
Method
时。
只会返回第一次的错误信息,不会返回 RemedyPlan
的错误信息。
fun ignored(): Result
+
变更记录
v1.0.0
添加
功能描述
忽略异常并停止打印任何错误日志。
注意
此时若要监听异常结果,你需要手动实现 onNoSuchMethod 方法。
inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
+
变更记录
v1.0.0
添加
功能描述
Method
实例处理类。
fun call(vararg args: Any?): Any?
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,不指定返回值类型。
fun <T> invoke(vararg args: Any?): T?
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定T
返回值类型。
fun byte(vararg args: Any?): Byte?
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Byte 返回值类型。
fun int(vararg args: Any?): Int
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Int 返回值类型。
fun long(vararg args: Any?): Long
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Long 返回值类型。
fun short(vararg args: Any?): Short
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Short 返回值类型。
fun double(vararg args: Any?): Double
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Double 返回值类型。
fun float(vararg args: Any?): Float
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Float 返回值类型。
fun string(vararg args: Any?): String
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 String 返回值类型。
fun char(vararg args: Any?): Char
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Char 返回值类型。
fun boolean(vararg args: Any?): Boolean
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Boolean 返回值类型。
inline fun <reified T> array(vararg args: Any?): Array<T>
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 Array 返回值类型。
inline fun <reified T> list(vararg args: Any?): List<T>
+
变更记录
v1.0.0
添加
功能描述
执行
Method
,指定 List 返回值类型。
object YLog
+
变更记录
v1.0.3
新增
功能描述
全局 Log 管理类。
object Configs
+
变更记录
v1.0.3
新增
功能描述
配置
YLog
。
var tag: String
+
变更记录
v1.0.3
新增
功能描述
这是一个调试日志的全局标识。
默认文案为 YukiReflection
。
你可以修改为你自己的文案。
var isEnable: Boolean
+
变更记录
v1.0.3
新增
功能描述
是否启用调试日志的输出功能。
关闭后将会停用 YukiReflection
对全部日志的输出。
当 isEnable
关闭后 YukiReflection.Configs.isDebug
也将同时关闭。
变更记录
v1.0.0
添加
功能描述
这是一个预置反射类型的常量类,主要为
Android
相关组件的Class
内容,跟随版本更新会逐一进行增加。
详情可 点击这里 进行查看。
变更记录
v1.0.0
添加
功能描述
这是一个预置反射类型的常量类,主要为
Android
相关Graphics
的Class
内容,跟随版本更新会逐一进行增加。
详情可 点击这里 进行查看。
变更记录
v1.0.0
添加
功能描述
这是一个预置反射类型的常量类,主要为
Android
相关Widget
的Class
内容,跟随版本更新会逐一进行增加。
详情可 点击这里 进行查看。
变更记录
v1.0.0
添加
功能描述
这是一个内部类型的定义常量类,主要用于反射 API 相关用法的延伸。
val VagueType: Class<*>
+
变更记录
v1.0.0
添加
功能描述
得到模糊类型。
变更记录
v1.0.0
添加
功能描述
这是一个预置反射类型的常量类,主要为 Java 相关基本变量类型的
Class
内容,跟随版本更新会逐一进行增加。
详情可 点击这里 进行查看。
这里介绍了
YukiReflection
的基本配置方法。
YukiReflection
无需一些复杂的配置即可直接开始使用,且不会与 Java 原生的反射 API 冲突。
你可以在使用之前对 YukiReflection
进行一些功能配置。
你可以通过如下方式获取当前 YukiReflection
的标签和版本。
示例如下
// 获取标签
+val tag = YukiReflection.TAG
+// 获取版本
+val version = YukiReflection.VERSION
+
你可以通过获取版本进行一些不同版本差异的判断或用于显示在关于信息中。
小提示
更多功能请参考 YukiReflection。
你可以通过 YukiReflection.configs { ... }
方法或 YukiReflection.Configs
来配置相关功能。
你可以使用如下方式来自定义调试日志的标签。
API 内部的日志将会使用此标签进行打印。
示例如下
// 通过 configs 方法
+YukiReflection.configs {
+ debugLog {
+ tag = "YourCustomTag"
+ }
+}
+// 直接设置
+YLog.Configs.tag = "YourCustomTag"
+
你可以使用如下方式来启用或禁用 Debug 模式。
Debug 模式默认是关闭的,启用后将会打印详细日志 (例如反射查找功能的耗时) 到控制台。
示例如下
// 通过 configs 方法
+YukiReflection.configs {
+ isDebug = true
+}
+// 直接设置
+YukiReflection.Configs.isDebug = true
+
你可以使用如下方式来启用或禁用调试日志的输出功能。
此功能默认启用,关闭后将会停用 YukiReflection
对全部日志的输出。
示例如下
// 通过 configs 方法
+YukiReflection.configs {
+ debugLog {
+ isEnable = true
+ }
+}
+// 直接设置
+YLog.Configs.isEnable = true
+
为了一次性配置多个功能,你可以直接使用 YukiReflection.configs { ... }
方法进行配置。
示例如下
YukiReflection.configs {
+ debugLog {
+ tag = "YourCustomTag"
+ isEnable = true
+ }
+ isDebug = true
+}
+
小提示
更多功能请参考 YukiReflection.configs 方法、YukiReflection.Configs。
YukiReflection
是一个基于 Java 和 Android 平台的反射 API。
这是一个使用 Kotlin 基于 Java 原生反射 API 重新打造的一套简洁、高效的反射 API。
YukiReflection
同时也是 YukiHookAPI 正在使用的核心功能。
名称取自 《ももくり》女主 栗原 雪(Yuki)。
YukiReflection
完全采用 Kotlin lambda 语法构建。
它能取代 Java 原生的反射 API,使用更加人性化的语言实现一套更加完善的反射方案。
请使用 Kotlin,API 部分代码构成同样兼容 Java 但基础反射场景的实现可能完全无法使用。
文档全部的 Demo 示例代码都将使用 Kotlin 进行描述,如果你完全不会使用 Kotlin 那你将有可能无法使用 YukiReflection
。
YukiReflection
最初是集成在 YukiHookAPI 项目中的核心功能,现在进行了解耦合,使得这套反射 API 可以在任何 Java 和 Android 平台的项目中使用。
现在,我们只需要编写少量的代码,就能实现一个简单的反射调用。
借助 Kotlin 优雅的 lambda 写法以及 YukiReflection
,可以让你的反射逻辑更加美观清晰。
示例如下
"android.os.SystemProperties".toClass()
+ .method {
+ name = "get"
+ param(StringClass, StringClass)
+ }.get().call("ro.system.build.fingerprint", "none")
+
Class.forName("android.os.SystemProperties")
+ .getDeclaredMethod("get", String::class.java, String::class.java)
+ .apply { isAccessible = true }
+ .invoke(null, "ro.system.build.fingerprint", "none")
+
集成
YukiReflection
到你的项目中。
Windows 7 及以上/macOS 10.14 及以上/Linux 发行版 (Arch/Debian)
Android Studio 2021.1 及以上
IntelliJ IDEA 2021.1 及以上
Kotlin 1.7.0 及以上
Android Gradle Plugin 7.0 及以上
Gradle 7.0 及以上
Java 11 及以上
Java 17 及以上 (Since API 1.0.3
)
项目需要使用 Android Studio
或 IntelliJ IDEA
创建且类型为 Java 或 Android 项目并已集成 Kotlin 环境依赖。
我们推荐使用 Kotlin DSL 作为 Gradle 构建脚本语言并推荐使用 SweetDependency 来管理依赖。
在你的项目 SweetDependency
配置文件中添加存储库和依赖。
示例如下
repositories:
+ # MavenCentral 有 2 小时缓存,若无法集成最新版本请添加
+ sonatype-oss-releases:
+
+libraries:
+ com.highcapable.yukireflection:
+ api:
+ version: +
+ ...
+
添加完成后运行一次 Gradle Sync,所有依赖版本将自动装配。
接下来,在你的项目 build.gradle.kts
中部署依赖。
示例如下
dependencies {
+ implementation(com.highcapable.yukireflection.api)
+ // ...
+}
+
在你的项目 build.gradle.kts
或 build.gradle
中添加存储库。
Kotlin DSL
repositories {
+ google()
+ mavenCentral()
+ // MavenCentral 有 2 小时缓存,若无法集成最新版本请添加此地址
+ maven { url("https://s01.oss.sonatype.org/content/repositories/releases/") }
+}
+
Groovy DSL
repositories {
+ google()
+ mavenCentral()
+ // MavenCentral 有 2 小时缓存,若无法集成最新版本请添加此地址
+ maven { url 'https://s01.oss.sonatype.org/content/repositories/releases/' }
+}
+
在你的项目 build.gradle.kts
或 build.gradle
中添加依赖。
Kotlin DSL
dependencies {
+ implementation("com.highcapable.yukireflection:api:<yuki-version>")
+ // ...
+}
+
Groovy DSL
dependencies {
+ implementation 'com.highcapable.yukireflection:api:<yuki-version>'
+ // ...
+}
+
请将 <yuki-version> 修改为 这里 的最新版本。
特别注意
如果你的项目目前正在使用 YukiHookAPI 的 1.x.x 版本,请不要重复集成 YukiReflection,因为 YukiHookAPI 已经包含了其中的功能且存在针对相关功能的改动,重复集成会造成功能性冲突引发异常,此时你应该前往 YukiHookAPI 的 文档 查看对应的使用教程。
YukiHookAPI 将在 2.0.0 版本完全分离 YukiReflection,届时你可以同时与 YukiHookAPI 使用。
在你的项目 build.gradle.kts
或 build.gradle
中修改 Kotlin 的 Java 版本为 17 及以上。
Kotlin DSL
android {
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+}
+
Groovy DSL
android {
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = '17'
+ }
+}
+
注意
自 API 1.0.3 版本后 Kotlin 使用的 Java 版本默认为 17,不再支持 11 及以下版本。