Initial commit

This commit is contained in:
2025-06-25 19:05:35 +08:00
commit e949662e7c
104 changed files with 11697 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
# About This Document
> This document is powered by [VuePress](https://v2.vuepress.vuejs.org/en).
## License
[Apache-2.0](https://github.com/HighCapable/KavaRef/blob/main/LICENSE)
```:no-line-numbers
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

View File

@@ -0,0 +1,29 @@
# Changelog
> The version update history of `KavaRef` is recorded here.
::: danger
We will only maintain the latest API version, if you are using an outdate API version, you voluntarily renounce any possibility of maintenance.
:::
::: warning
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**
:::
## kavaref-core
### 1.0.0 | 2025.06.25 &ensp;<Badge type="tip" text="latest" vertical="middle" />
- The first version is submitted to Maven
## kavaref-extension
### 1.0.0 | 2025.06.25 &ensp;<Badge type="tip" text="latest" vertical="middle" />
- The first version is submitted to Maven

View File

@@ -0,0 +1,16 @@
# Contact Us
> If you have any questions in use, or have any constructive suggestions, you can contact us.
Join our developers group.
- [Click to join Telegram group](https://t.me/KavaRef)
- [Click to join Telegram group (Developer))](https://t.me/HighCapable_Dev)
Find me on **Twitter** [@fankesyooni](https://twitter.com/fankesyooni).
## Help with Maintenance
Thank you for choosing and using `KavaRef`.
If you have code-related suggestions and requests, you can submit a Pull Request on GitHub.

View File

@@ -0,0 +1,114 @@
# Looking for Future
> The future is bright and uncertain, let us look forward to the future development space of `KavaRef`.
## Future Plans
> Features that `KavaRef` may add later are included here.
### Supports Class Filtering through ClassLoader
`KavaRef` currently only supports search and calls for reflection APIs such as `Method`, `Field`, and `Constructor`.
In the future, the ability to filter `Class` by specified type `ClassLoader` may be supported in Java and Android platforms according to requirements.
Currently, you can use [DexKit](https://github.com/LuckyPray/DexKit) to complete this requirement,
which also supports more complex searches and calls of reflective APIs such as Method, Field, and Constructor.
### Automatically Generate Reflection Code
**This is a feature that has been initially established in [YukiReflection](https://github.com/HighCapable/YukiReflection), and `KavaRef` is ready to continue to implement it in the possible time in the future.**
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
```java:no-line-numbers
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
```kotlin
MyClass().resolve().apply {
// Call myField.
val value = firstField { name = "myField" }.get<String>()
// Call myMethod1.
val methodValue = firstMethod { name = "myMethod1" }.invoke<String>("test", 0)
// Call myMethod2.
firstMethod { name = "myMethod2" }.invoke()
// Call myMethod3.
firstMethod { name = "myMethod3" }.invoke("test")
}
```
The function to be implemented at present can be directly defined as the following Kotlin class using the reflection function.
> The following example
```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
}
```
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
```kotlin
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")
}
```
::: tip
The above functions may change after the actual release, and the functions of the actual version shall prevail.
:::

View File

@@ -0,0 +1,266 @@
# Migration to KavaRef
If you are used to using the reflection API in [YukiReflection](https://github.com/HighCapable/YukiReflection) or [YukiHookAPI](https://github.com/HighCapable/YukiHookAPI), you can refer to the following to migrate to `KavaRef`.
::: warning
For `YukiHookAPI`, you need to continue using its Hook API, and `KavaRef` only includes Java reflection-related APIs.
:::
## Basic Functions
The design concept of `KavaRef` is similar to `YukiReflection`, but not exactly the same.
The following lists the differences between `YukiReflection` and `KavaRef` in basic reflection functions, which you can manually migrate based on.
For example, we have the following Java class.
> The following example
```java :no-line-numbers
public class MyClass {
private void myMethod(String content) {
System.out.println("Hello " + content + "!");
}
}
```
Here is a comparison of `KavaRef` with `YukiReflection` using examples.
> The following example
<div style="display: flex; gap: 16px;">
<div style="flex: 1;">
<h4>KavaRef</h4>
```kotlin
// Assume that's your MyClass instance.
val myClass: MyClass
// Call and execute using KavaRef.
MyClass::class.resolve().firstMethod {
name = "myMethod"
parameters(String::class)
}.of(myClass).invoke("Hello, KavaRef!")
// Direct reference to instance.
myClass.resolve().firstMethod {
name = "myMethod"
parameters(String::class)
}.invoke("Hello, KavaRef!")
```
</div>
<div style="flex: 1;">
<h4>YukiReflection</h4>
```kotlin
// Assume that's your MyClass instance.
val myClass: MyClass
// Call and execute using YukiReflection.
MyClass::class.java.method {
name = "myMethod"
param(StringClass)
}.get(myClass).call("Hello, YukiReflection!")
// Direct reference to instance.
myClass.current().method {
name = "myMethod"
param(StringClass)
}.call("Hello, YukiReflection!")
```
</div>
</div>
`KavaRef` starts reflection at any time, you need to use `resolve()` to create a reflection scope.
You no longer directly extend the related `method` and `constructor` methods to avoid contaminating their scope.
`KavaRef` abandons the "Finder" design concept and uses the "Filter" design concept to obtain reflected results.
"Find" is no longer a finding, but a "filtering".
`KavaRef` canceled the `YukiReflection` defined in the resulting instance whether the `Member` obtained is a multiple or a single design scheme,
and directly returns the entire `List<MemberResolver>`.
The example you see above uses `firstMethod` to get the first match `MethodResolver`,
if you need to get all matches, you can change to `method`.
The conditional method name of `KavaRef` in `MethodCondition` has been modified from abbreviation
such as `param` before `YukiReflection` to `parameters` to more in line with the naming habit of Java reflection API.
`KavaRef` no longer provides the `param(...).order()` function in the condition, because this function itself is unstable.
`KavaRef` now uses an iterator for filtering, and the bytecode will no longer be in order, and the bytecode should not be filtered in order.
You can use `firstMethod`, `firstField`, or `lastMethod`, `lastField`, etc. to get the first or last match result.
`KavaRef` renames the `get(instance)` method to `of(instance)` because `get(...)` may be confused with the `get(...)` usage of `Field` and is not semantic,
At the same time, `get(instance)` is no longer getting the `MethodFinder.Result.Instance` instance from something like `MethodFinder.Result`,
but uses `of(instance)` to always operate and set the instance object to `MemberResolver`.
Methods such as `string()`, `int()`, etc. in `MethodFinder.Result.Instance` have been removed in `KavaRef`.
You can directly use `get<String>()`, `get<Int>()`, `invoke<String>(...)`, `invoke<Int>(...)`, etc. to get or call the corresponding type results.
::: danger
If you are looking for (filtering) `Field`, you need to note that there may be semantic conflicts between `KavaRef` and `YukiReflection` in the acquisition method of `Field`.
Please pay special attention when migrating this part.
For example, get the static field of `content` in `MyClass`, in `YukiReflection`, you would do this.
> The following example
```kotlin
MyClass::class.java
.field { name = "content" } // Return FieldFinder.Result
.get() // Cannot be omitted, return FieldFinder.Result.Instance
.string() // value
```
In `KavaRef` you need to do this.
> The following example
```kotlin
MyClass::class.resolve()
.firstField { name = "content" } // Return FieldResolver<MyClass>
.get<String>() // value
```
As mentioned above, `get(...)` is used to get the `FieldFinder.Result.Instance` object in Y`ukiReflection`, not the value.
To get the value and process it as a specified type, you need to call `string()` or `cast<String>()`, and in `KavaRef`,
you use `get<T>()` directly in `MemberResolver` to get the value of the specified type.
The usage of `get(...)` of `KavaRef` for `get(...)` to `of(...)`.
So the complete writing of the above example in `KavaRef` should be.
> The following example
```kotlin
// Since the call is a static instance, "of(null)" can be omitted.
MyClass::class.resolve()
.firstField { name = "content" } // It's already a call chain object FieldResolver<MyClass>
.of(null) // Can be omitted and return to the call chain object FieldResolver<MyClass>
.get<String>() // value
```
:::
`KavaRef` no longer provides `call` methods for `Method`, and is now merged uniformly into `invoke` (with generic parameters).
At the same time, `KavaRef` defines the `newInstance` method of `Constructor` as `create` (with generic parameters).
You may have noticed that the condition `superClass()` is gone, it is still there,
in `KavaRef` it has been renamed to `superclass()`, docking with the standard Java reflection API.
At the same time, `KavaRef` extends `KClass`, and you no longer need to use `Some::class.java` to declare an instance of `Class` in most scenarios.
Another design idea of `KavaRef` is type safety.
As long as you use `KClass<T>` and `Class<T>` that declare the generic type, it will be checked and converted to the
corresponding type when `of(instance)` and `create(...)`, and type checking will be completed during coding to avoid runtime errors.
> The following example
```kotlin
// Assume that's your MyClass instance.
val myClass: MyClass
// Using KavaRef to call and execute.
MyClass::class
.resolve()
.firstMethod {
name = "myMethod"
parameters(String::class)
}
// Only instances of type MyClass can be passed in.
.of(myClass)
.invoke("Hello, KavaRef!")
```
## Other Functions
`KavaRef` and `YukiReflection` are not much different in other functions and extended functions.
`KavaRef` separates these functions into a separate module.
The following functionality is provided in `YukiReflection` but is not implemented and no longer provided in `KavaRef`:
- Preset reflection type constant classes, such as `StringClass`, `IntType`, etc
- You can use Kotlin class references such as `String::class`, `Int::class`, etc. to replace it.
For primitive types and wrapper classes, `IntType` is equivalent to `Int::class`, and `IntClass` is equivalent to `JInteger::class`
- `DexClassFinder` function
- Due to its design flaws and possible performance issues when used on Android platforms, it is no longer available for now
- `RemedyPlan` and `method { ... } .remedys { ... }` functions
- Due to possible black box problems, maintenance is relatively difficult.
If you need to use similar functions, please implement them manually and will no longer be provided
- `ClassLoader.listOfClasses()` function
- Due to the complex and unstable implementation solutions of each platform, it will no longer be provided
- `ClassLoader.searchClass()` function
- Due to performance issues and design time is limited to Android platform,
it is relatively difficult to maintain filter conditions and is no longer provided
- `Class.hasExtends`, `Class.extends`, `Class.implements` functions
- You can replace them with `A::class isSubclassOf B::class`
- `Class.toJavaPrimitiveType()` function
- There is conceptual confusion in functional design and will no longer be provided
- `"com.some.clazz".hasClass(loader)` function
- You can use `loader.hasClass("com.some.clazz")` to replace it
- `Class.hasField`, `Class.hasMethod`, `Class.hasConstructor` functions
- Due to design defects, no longer provided
- `Class.hasModifiers(...)`, `Member.hasModifiers(...)` functions
- You can replace them directly with extension methods such as `Class.isPublic`, `Member.isPublic`
- `Class.generic()`, `GenericClass` functions
- If you just want to get generic parameters of the superclass, you can use `Class.genericSuperclassTypeArguments()`.
Due to design defects, no longer provided
- `Class.current()`, `CurrentClass` functions
- Merged into the core function of `KavaRef.resolve()` and is no longer provided separately
- `Class.buildOf(...)` function
- You can use `Class.createInstance(...)` to replace it
- `Class.allMethods()`, `Class.allFields()`, `Class.allConstructors()` functions
- Due to its pollution scope, no longer provided
- `YLog` log function
- `KavaRef` no longer takes over the logs, you can use the corresponding platform implementation method and no longer provided
## Exception Handling
`KavaRef` is completely different from `YukiReflection` in exception handling.
The exception logic of `KavaRef` will remain transparent by default. <u>**It no longer actively intercepts exceptions and prints error logs or even provides `onNoSuchMethod` listener**</u>.
When no valid members are filtered, `KavaRef` will throw an exception directly unless you **explicitly declare the condition as optional (consistent with `YukiReflection` logic)**.
> The following example
```kotlin
// Assume that's your MyClass instance.
val myClass: MyClass
// Using KavaRef to call and execute.
MyClass::class
.resolve()
.optional() // Declare as optional, do not throw exceptions.
// Use firstMethodOrNull instead of firstMethod,
// because the NoSuchElementException of Kotlin itself will be thrown.
.firstMethodOrNull {
name = "doNonExistentMethod" // Assume that this method does not exist.
parameters(String::class)
}?.of(myClass)?.invoke("Hello, KavaRef!")
```
For more information, please refer to the [Exception Handling](../library/kavaref-core.md#exception-handling) section in [kavaref-core](../library/kavaref-core.md).
## New to KavaRef
If you haven't used `YukiReflection` or `YukiHookAPI`, it doesn't matter, you can refer to the following content to get started quickly.
::: tip What to Do Next
For more information, please continue reading [kavaref-core](../library/kavaref-core.md) and [kavaref-extension](../library/kavaref-extension.md).
Get started using `KavaRef` now!
:::

View File

@@ -0,0 +1,37 @@
# Third-party Member Resolvers
> Here are some third-party Member resolvers for reference and use.
>
> Please read [Custom Resolver](../library/kavaref-core.md#custom-resolver) for usage.
## AndroidHiddenApiBypass
[Project URL](https://github.com/LSPosed/AndroidHiddenApiBypass)
> LSPass: Bypass restrictions on non-SDK interfaces
```kotlin
class AndroidHiddenApiBypassResolver : MemberProcessor.Resolver() {
override fun <T : Any> getDeclaredConstructors(declaringClass: Class<T>): List<Constructor<T>> {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
return super.getDeclaredConstructors(declaringClass)
}
val constructors = HiddenApiBypass.getDeclaredMethods(declaringClass)
.filterIsInstance<Constructor<T>>()
.toList()
return constructors
}
override fun <T : Any> getDeclaredMethods(declaringClass: Class<T>): List<Method> {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
return super.getDeclaredMethods(declaringClass)
}
val methods = HiddenApiBypass.getDeclaredMethods(declaringClass)
.filterIsInstance<Method>()
.toList()
return methods
}
}

View File

@@ -0,0 +1,6 @@
# R8 & Proguard Obfuscate
> In most scenarios, Android application installation packages can compress volumes through obfuscation.
> Here is a configuration method for obfuscation rules.
`KavaRef` does not require any additional configuration of obfuscation rules in Android projects.

View File

@@ -0,0 +1,46 @@
# Introduce
> `KavaRef` is a modern Java reflection API implemented using Kotlin.
## Background
This is a modern Java reflection API implemented using Kotlin, designed to provide a cleaner and easier-to-use API while retaining the power of Java
reflection.
The project icon is designed by [MaiTungTM](https://github.com/Lagrio) and is named from **K**otlinJ**avaRef**lection, meaning Java reflection
implemented using Kotlin.
It was firstborn in the [YukiHookAPI](https://github.com/HighCapable/YukiHookAPI), and was later decoupled into
the [YukiReflection](https://github.com/HighCapable/YukiReflection) project.
As you can see, now `KavaRef` is a completely new set of APIs completely refactored with the design idea of `YukiReflection`,
which has no affiliation and will replace `YukiReflection` as a new reflection solution.
If you are using `YukiReflection` or the `YukiHookAPI` project related to it, you can refer to [here](../config/migration) to migrate the reflection API to `KavaRef`.
## Usage
`KavaRef` is built in Kotlin **lambda** syntax with Java Builder style.
It can replace [Java's native Reflection API](https://www.oracle.com/technical-resources/articles/java/javareflection.html) and implement a more complete reflection solution in a more human-friendly language.
## Skill Requirements
You must be proficient in Java's native reflection APIs, understand Java's class loading mechanisms, bytecode structures, and how they are used in Kotlin (if you are using Kotlin).
## Language Requirement
It is recommended to use Kotlin. API code composition also supports Java,
but in pure Java projects `KavaRef` may not be able to play its full functionality and syntactic sugar advantages.
All the demo sample code in the documentation will be described first using Kotlin.
If you don't know how to use Kotlin at all, you may not be able to experience and use the functionality of `KavaRef` more fully.
## Contribution
The maintenance of this project is inseparable from the support and contributions of all developers.
This project is currently in its early stages, and there may still be some problems or lack of functions you need.
If possible, feel free to submit a PR to contribute features you think are needed to this project or goto [GitHub Issues](repo://issues)
to make suggestions to us.

View File

@@ -0,0 +1,97 @@
# Quick Start
> Integrate `KavaRef` into your project.
## Project Requirements
The project needs to be created using `IntelliJ IDEA` or `Android Studio` and be of type Java or Android
project and have integrated Kotlin environment dependencies.
- IntelliJ IDEA (It is recommended to get the latest version [from here](https://www.jetbrains.com/idea))
- Android Studio (It is recommended to get the latest version [from here](https://developer.android.com/studio))
- Kotlin 1.9.0+, Gradle 8+, Java 17+
### Configure Repositories
The dependencies of `KavaRef` are published in **Maven Central** and our public repository,
you can use the following method to configure repositories.
We recommend using Kotlin DSL as the Gradle build script language and [SweetDependency](https://github.com/HighCapable/SweetDependency)
to manage dependencies.
#### SweetDependency (Recommended)
Configure repositories in your project's `SweetDependency` configuration file.
```yaml
repositories:
google:
maven-central:
# (Optional) You can add this URL to use our public repository
# When Sonatype-OSS fails and cannot publish dependencies, this repository is added as a backup
# For details, please visit: https://github.com/HighCapable/maven-repository
highcapable-maven-releases:
url: https://raw.githubusercontent.com/HighCapable/maven-repository/main/repository/releases
```
#### Traditional Method
Configure repositories in your project `build.gradle.kts`.
```kotlin
repositories {
google()
mavenCentral()
// (Optional) You can add this URL to use our public repository
// When Sonatype-OSS fails and cannot publish dependencies, this repository is added as a backup
// For details, please visit: https://github.com/HighCapable/maven-repository
maven("https://raw.githubusercontent.com/HighCapable/maven-repository/main/repository/releases")
}
```
### Configure Java Version
Modify the Java version of Kotlin in your project `build.gradle.kts` to 17 or above.
> Java Project
```kt
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
```
> Android Project
```kt
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}
```
## Functional Overview
The project is divided into multiple modules. You can choose the module you wish to include as a dependency in your project, but be sure to include the **kavaref-core** module.
Click the corresponding module below to view detailed feature descriptions.
- [kavaref-core](../library/kavaref-core.md)
- [kavaref-extension](../library/kavaref-extension.md)
## Demo
You can find some samples [here](repo://tree/main/samples) view the corresponding demo project to better understand how these functions work and quickly
select the functions you need.

View File

@@ -0,0 +1,38 @@
---
home: true
title: Home
heroImage: /images/logo.svg
actions:
- text: Get Started
link: /en/guide/home
type: primary
- text: Changelog
link: /en/about/changelog
type: secondary
features:
- title: Light and Elegant
details: A powerful, elegant, beautiful API built with Kotlin lambda can help you quickly implement bytecode filtering and reflection functions.
- title: Fully Compatible
details: Using native Java APIs to implement reflection functionality, it can be used on any Kotlin on JVM project, and it is no problem on Android.
- title: Quickly Started
details: Simple and easy to use it now! Do not need complex configuration and full development experience, Integrate dependencies and enjoy yourself.
footer: Apache-2.0 License | Copyright (C) 2019 HighCapable
---
### Start reflecting anytime, anywhere.
```java
public class World {
private void sayHello(String content) {
System.out.println("Hello " + content + "!");
}
}
```
```kotlin
World().resolve().firstMethod {
name = "sayHello"
parameters(String::class)
}.invoke("KavaRef")
```

View File

@@ -0,0 +1,790 @@
# kavaref-core
![Maven Central](https://img.shields.io/maven-central/v/com.highcapable.kavaref/kavaref-core?logo=apachemaven&logoColor=orange&style=flat-square)
<span style="margin-left: 5px"/>
![Maven metadata URL](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fraw.githubusercontent.com%2FHighCapable%2Fmaven-repository%2Frefs%2Fheads%2Fmain%2Frepository%2Freleases%2Fcom%2Fhighcapable%2Fkavaref%2Fkavaref-core%2Fmaven-metadata.xml&logo=apachemaven&logoColor=orange&label=highcapable-maven-releases&style=flat-square)
This is the core dependency of KavaRef, and you need to introduce this module to use the basic features of KavaRef.
## Configure Dependency
You can add this module to your project using the following method.
### SweetDependency (Recommended)
Add dependency in your project's `SweetDependency` configuration file.
```yaml
libraries:
com.highcapable.kavaref:
kavaref-core:
version: +
```
Configure dependency in your project `build.gradle.kts`.
```kotlin
implementation(com.highcapable.kavaref.kavaref.core)
```
### Version Catalog
Add dependency in your project's `gradle/libs.versions.toml`.
```toml
[versions]
kavaref-core = "<version>"
[libraries]
kavaref-core = { module = "com.highcapable.kavaref:kavaref-core", version.ref = "kavaref-core" }
```
Configure dependency in your project `build.gradle.kts`.
```kotlin
implementation(libs.kavaref.core)
```
Please change `<version>` to the version displayed at the top of this document.
### Traditional Method
Configure dependency in your project `build.gradle.kts`.
```kotlin
implementation("com.highcapable.kavaref:kavaref-core:<version>")
```
Please change `<version>` to the version displayed at the top of this document.
## Function Introduction
You can view the KDoc [click here](kdoc://kavaref-core).
### Basic Usage
KavaRef adopts a chained call design, which creates extension methods for available Java reflection APIs (such as `Class`).
You only need to call `resolve()` to these contents to enter the world of KavaRef.
The relationship diagram is as follows.
``` :no-line-numbers
KavaRef
└── KClass/Class/Any.resolve()
├── method()
├── constructor()
└── field()
```
Next, we will give multiple examples of Java `Class`, which will be explained based on them in the future.
```java :no-line-numbers
package com.demo;
public class BaseTest {
public BaseTest() {
// ...
}
private void doBaseTask(String taskName) {
// ...
}
}
```
```java :no-line-numbers
package com.demo;
public class Test extends BaseTest {
private Test() {
// ...
}
private static TAG = "Test";
private boolean isTaskRunning = false;
private void doTask(String taskName) {
// ...
}
private void release(String taskName, Function<boolean, String> task, boolean isFinish) {
// ...
}
private void stop() {
// ...
}
private String getName() {
// ...
}
}
```
```java
public class Box<T> {
public void print(T item, String str) {
// ...
}
}
```
Suppose, we want to get the `doTask` method of `Test` and execute it. In KavaRef, you can do it in the following ways.
> The following example
```kotlin
// Suppose this is an instance of this Class.
val test: Test
//Reflect it by instantiating Class.
// In KavaRef you don't need to convert it to `java.lang.Class`,
// It will automatically call KClass.java.
Test::class
// Create KavaRef reflections.
.resolve()
// Create method condition.
.method {
// Set method name.
name = "doTask"
// Set method parameter type.
parameters(String::class)
}
// After the condition is executed, the matching List<MethodResolver>
// instance will be returned.
// Here we get the first filtering result.
.first()
// Setting an instance of Test on MethodResolver.
.of(test)
// Calling methods and passing in parameters.
.invoke("task_name")
```
In the above writing method, we use `Test::class.resolve()` to get the KavaRef reflection instance of the current `Class`.
Then create a method filtering condition `MethodCondition` by `method { ... }`, which sets the method name and parameter type, and returns the `List<MethodResolver>` instance after execution.
Then we use `first()` to get the first matched `MethodResolver` instance,
Then use `of(test)` to set the current instance of `Class`, and finally use `invoke("task_name")` to execute the method and pass in the parameters.
In this, MethodCondition is inherited from MemberCondition, which allows you to conditionally filter the Method, which contains a conditional image of the Java-core reflection API.
You can view the corresponding comments to understand the native usage of each API.
Similarly, MethodResolver is inherited from `MemberResolver`, which allows you to make reflection calls to `Method` in the filtered result.
Since the reflection requirement here is to obtain a available method result, the call chain of `method { ... }.first()` may be more cumbersome,
and at this time there is the following simplification solution.
> The following example
```kotlin
Test::class
.resolve()
// Use firstMethod directly to get the first matching
// MethodResolver instance.
.firstMethod {
name = "doTask"
parameters(String::class)
}
.of(test)
.invoke("task_name")
```
Since we can now get an instance of `Test`, there is also a simplified way to write it,
you can use this instance to create KavaRef reflections directly.
> The following example
```kotlin
// Here, the test instance test will be passed to
// KavaRef and get test::class.java.
test.resolve()
.firstMethod {
name = "doTask"
parameters(String::class)
} // Since you set up an instance, of(test) is no longer needed here.
.invoke("task_name")
```
Next, we need to get the `isTaskRunning` variable, which can be written in the following form.
> The following example
```kotlin
// Suppose this is an example of this Class.
val test: Test
// Call and execute with KavaRef.
val isTaskRunning = test.resolve()
.firstField {
name = "isTaskRunning"
type = Boolean::class
}.get<Boolean>()
```
The constructor in `Test` is privatized, and now we can create an instance of it using the following method.
> The following example
```kotlin
val test = Test::class.resolve()
.firstConstructor {
// For the zero parameter construction method,
// the following conditions can be used to filter.
// It is equivalent to parameterCount = 0.
emptyParameters()
}.create() // Create a new Test instance.
```
You can also use `createAsType<T>()` to specify its superclass type `BaseTest` for the actual object `Test`.
> The following example
```kotlin
val test = Test::class.resolve()
.firstConstructor {
emptyParameters()
}.createAsType<BaseTest>() // Create a new BaseTest instance.
```
::: tip
In addition to methods such as `firstMethod`, you can also use methods such as `lastMethod` to get the last matching `MethodResolver` instance, which is equivalent to `method { ... }.last()`.
After you get the `MemberResolver` instance, you can use `self` to get the `Member` original instance of the current `MemberResolver` to do some of your own operations.
In `MemberResolver` inherited from `InstanceAwareResolver` (for example `MethodResolver` and `FieldResolver`), you can use `of(instance)`
To set the current instance, if the reflection is static (static) member, you do not need to set the instance.
:::
::: danger
In `MemberResolver` inherited from `InstanceAwareResolver`, the type of `of(instance)` requires the same type as the currently reflected `Class` instance generic type.
Unless the `Class` generic type is not specified, or the `Class` generic type is set to `Any`.
If `of(instance)` appears `Required: Nothing?` error (this is usually due to `Class` created via `Class.forName(...)` or `ClassLoader.loadClass(...)`),
then your `Class` is `Class<*>` (in Java it is `Class<?>`).
At this time, if you do not want to specify the type, please set or convert it to `Class<Any>`, just like the following.
> The following example
```kotlin
val myClass = Class.forName("com.xxx.MyClass") as Class<Any>
// Suppose this is an example of this Class.
val myClassInstance: Any
myClass.resolve()
.firstMethod {
// ...
}.of(myClassInstance).invoke(...)
```
You can also use [Create Class Object](kavaref-extension.md#create-class-object) provided in [kavaref-extension](kavaref-extension.md) to solve this problem.
:::
### Vague Conditions
You will notice that there is a `release` method in `Test`, but its method parameters are very long and some types may not be directly obtained.
At this point, you can use the `parameters(...)` condition to use `VagueType` to fill in the method parameter types you don't want to fill in.
> The following example
```kotlin
// Suppose this is an example of this Class.
val test: Test
// Call and execute with KavaRef.
test.resolve()
.firstMethod {
name = "release"
// Use VagueType to fill in the types you don't want to fill in,
// and ensure that other types can match.
parameters(String::class, VagueType, Boolean::class)
} // Get this method.
```
::: warning
`VagueType` can only be used when there are filter conditions with multiple parameters,
it cannot be used in filter conditions with only a single parameter, such as `type`.
You can create it using `VagueType`, `VagueType::class` or `VagueType::class.java`, all of which are correctly recognized as fuzzy filtering conditions.
:::
### Freedom Conditions
In `MemberCondition`, `name`, `type`, `parameterCount` and other conditions can all use the Kotlin lambda feature to create free filtering conditions.
Suppose we want to get the `doTask` method in `Test`, we can use the following implementation.
> The following example
```kotlin
// Suppose this is an example of this Class.
val test: Test
// Call and execute with KavaRef.
test.resolve()
.firstMethod {
// Use lambda to set the method name.
name {
// Set the name not case sensitive.
it.equals("dotask", ignoreCase = true)
}
// Set parameter type.
parameters(String::class)
}.invoke("task_name")
```
### Generic Conditions
KavaRef supports adding generic filtering conditions, which you can use the relevant functions provided by `TypeMatcher`.
Suppose we need to filter the `print` method in `Box<String>`.
> The following example
```kotlin
// Suppose this is an example of this Class.
val box: Box<String>
// Call and execute with KavaRef.
box.resolve()
.firstMethod {
name = "print"
// Set generic parameter conditions.
genericParametes(
// Filter generic name "T".
typeVar("T"),
// Create TypeMatcher through Class.
String::class.toTypeMatcher()
)
}.invoke("item", "str")
```
### Filter in Superclass
You will notice that `Test` inherits from `BaseTest`, and now we want to get the `doBaseTask` method of `BaseTest`.
Without knowing the superclass name, we only need to add `superclass()` to the filter condition to achieve this function.
> The following example
```kotlin
// Suppose this is an example of this Class.
val test: Test
// Call and execute with KavaRef.
test.resolve()
.firstMethod {
name = "doBaseTask"
parameters(String::class)
// Just add this condition.
superclass()
}.invoke("task_name")
```
At this time, we can get this method in the superclass.
::: tip
`superclass()` once set it,it will automatically loop backwards whether there is this method in all inherited
superclasses until the target has no superclass (the inheritance relationship is `java.lang.Object`).
:::
::: danger
The current filtering method can only filter to the current `Class` method unless the `superclass()` condition is specified,
which is the default behavior of the Java reflection API.
KavaRef will call `Class.getDeclaredMethods()` to get the current `Class` method instead of `Class.getMethods()`.
:::
### Other Conditions
KavaRef provides some filtering conditions to assist in the use of the Java reflection API.
Suppose we want to get the contents of the static variable `TAG` in `Test`.
In order to reflect that the filtering conditions include static descriptors, we can implement them using the following methods.
> The following example
```kotlin
val tag = Test::class.resolve()
.firstField {
name = "TAG"
type = String::class
// Create descriptor filtering.
modifiers(Modifiers.STATIC)
// Or.
modifiers {
it.contains(Modifiers.STATIC)
}
}.get<String>() // Get field content.
```
You can also use string types to pass in full class names in conditions such as `type`, `parameters`, etc.
> The following example
```kotlin
// Suppose this is an example of this Class.
val test: Test
// Call and execute with KavaRef.
test.resolve()
.firstMethod {
name = "doTask"
// Pass the full class name using string type.
parameters("java.lang.String")
}.invoke("task_name")
```
### Exception Handling
By default, KavaRef throws an exception when a member is not found during a reflection call.
> The following example
```kotlin
Test::class.resolve()
.method {
name = "doNonExistentMethod"
} // NoSuchMethodException will be thrown here.
```
If you do not want an exception to be thrown, you can set the optional condition `optional()`.
> The following example
```kotlin
Test::class.resolve()
// Set optional conditions.
.optional()
.method {
name = "doNonExistentMethod"
} // Return empty List<MethodResolver>.
```
KavaRef prints the complete exception content for debugging, and when using `optional()`, the exception is printed as a WARN level log.
> The following example
``` :no-line-numbers
No method found matching the condition for current class.
+------------------------------------------------+
| class com.demo |
+------------+-----------------------------------+
| name | doNonExistentMethod |
| parameters | [class java.lang.String, boolean] |
+------------+-----------------------------------+
```
If you don't want KavaRef to throw or print anything, you can use `optional(silent = true)` to silently handle it,
but we **do not recommend this**, which will mask the problem unless it is necessary.
::: danger
If you set `optional()`, please do not use `firstMethod`, `firstConstructor` and other methods to get a single result.
Because they throw an exception with empty list when there is no result, you can use the method with the suffix `OrNull` to get a single result.
:::
### Log Management
KavaRef provides its own log management function, you can set the log level through `KavaRef.logLevel`.
You can set `KavaRef.logLevel = KavaRefRuntime.LogLevel.DEBUG` to enable DEBUG level logs so that KavaRef
prints more detailed step-by-step filtering condition logs to the console during the filtering process.
If you want to turn off all log printing of KavaRef, you can set `KavaRef.logLevel = KavaRefRuntime.LogLevel.OFF`.
If you have more advanced requirements, you can implement `KavaRefRuntime.Logger` to customize your own log printing method.
> The following example
```kotlin
class MyLogger : KavaRefRuntime.Logger {
// Here you can specify the tag for log printing.
override val tag = "MyLogger"
override fun debug(msg: Any?, throwable: Throwable?) {
// Implement your log printing logic here.
}
override fun info(msg: Any?, throwable: Throwable?) {
// Implement your log printing logic here.
}
override fun warn(msg: Any?, throwable: Throwable?) {
// Implement your log printing logic here.
}
override fun error(msg: Any?, throwable: Throwable?) {
// Implement your log printing logic here.
}
}
```
Then, set it to KavaRef.
> The following example
```kotlin
KavaRef.setLogger(MyLogger())
```
### Advanced Usage
The above content explains all the usage methods in standard scenarios.
If you have a more fine-grained usage scenario, you can manually create related components of KavaRef.
If you don't like the Kotlin lambda writing, you can create chained calls manually.
> The following example
```kotlin
// Suppose this is an example of this Class.
val test: Test
// Call and execute with KavaRef.
test.resolve()
.method() // Conditions begin.
.name("doTask")
.parameters(String::class)
.build() // Conditions ends (executes)
.first()
.invoke("task_name")
```
You can also manually create any filtering conditions to achieve multiplexing it in any reflection.
> The following example
```kotlin
// Suppose this is an example of this Class.
val test: Test
// Create MethodCondition manually.
val condition = MethodCondition<Test>()
condition.name = "doTask"
condition.parameters(String::class)
// Apply condition to reflection object.
Test::class.resolve()
.firstMethod(condition)
.of(test) // Setting up instance.
.invoke("task_name")
```
Alternatively, you can also manually and completely implement the entire reflection process.
> The following example
```kotlin
// Suppose this is an example of this Class.
val test: Test
// Create MethodCondition manually.
val condition = MethodCondition<Test>()
condition.name = "doTask"
condition.parameters(String::class)
// Create MemberCondition.Configuration manually.
val configuration = Test::class.java.createConfiguration(
memberInstance = test, // Setting up instance.
processorResolver = null, // Use the default resolver, refer to the "Custom Resolver" below.
superclass = false, // Whether to filter in superclass.
optional = MemberCondition.Configuration.Optional.NO // Configure optional conditions.
)
// Create and start filtering.
val resolvers = condition.build(configuration)
// Get the first result.
val resolver = resolvers.first()
// Execute the method.
resolver.invoke("task_name")
```
If you have more advanced requirements for business layer logic, you can also use `mergeWith` to merge multiple filter conditions.
> The following example
```kotlin
// Suppose this is an instance of this Class.
val test: Test
// Create MethodCondition manually.
// Create the first condition.
val condition1 = MethodCondition<Test>()
condition1.name = "doTask"
// Create a second condition.
val condition2 = MethodCondition<Test>()
condition2.parameters(String::class)
// Merge condition2 into condition1.
// At this time, the condition of condition1 will contain the condition that condition2 is not null.
// The duplicated conditions in condition1 will be overwritten by the condition2 condition.
condition1.mergeWith(condition2)
// You can also use the infix syntax.
condition1 mergeWith condition2
// Call and execute with KavaRef.
Test::class.resolve()
.firstMethod(condition1)
.of(test)
.invoke("task_name")
```
::: danger
Reused use of `build(...)` will no longer be allowed for creation when `MemberCondition.Configuration` is set.
At this point you need to use `copy()` to copy and create a new `MemberCondition`.
Similarly, `InstanceAwareResolver` is not allowed to duplicately set up new instances after setting the instance via `MemberCondition.Configuration.memberInstance` or `of(instance)`.
At this time, you also need to use `copy()` to copy and create a new `InstanceAwareResolver`.
:::
### Custom Resolver
KavaRef uses the default `Member` resolver for filtering.
If you want to implement your own resolver, you can customize the global and the resolver used for each reflection process.
You can inherit from `MemberProccessor.Resolver` to implement your own resolver.
> The following example
```kotlin
class MyMemberProcessorResolver : MemberProcessor.Resolver() {
override fun <T : Any> getDeclaredConstructors(declaringClass: Class<T>): List<Constructor<T>> {
// Intercept and implement your constructor filtering logic here.
return super.getDeclaredConstructors(declaringClass)
}
override fun <T : Any> getDeclaredMethods(declaringClass: Class<T>): List<Method> {
// Intercept and implement your method filtering logic here.
return super.getDeclaredMethods(declaringClass)
}
override fun <T : Any> getDeclaredFields(declaringClass: Class<T>): List<Field> {
// Intercept and implement your field filtering logic here.
return super.getDeclaredFields(declaringClass)
}
}
```
You can then set it to the global configuration.
> The following example
```kotlin
MemberProcessor.globalResolver = MyMemberProcessorResolver()
```
Alternatively, during each reflection, you can set up a custom resolver using `MemberCondition.Configuration` or use a chain call to set up a resolver.
> The following example
```kotlin
// Create resolver.
val myResolver = MyMemberProcessorResolver()
// Suppose this is an instance of this Class.
val test: Test
// Call and execute using KavaRef.
test.resolve()
// Set custom resolver.
.processor(myResolver)
.firstMethod {
name = "doTask"
parameters(String::class)
}.invoke("task_name")
```
::: tip
You can find some publicly maintained custom solvers in [here](../config/processor-resolvers.md) and define them in your project to use.
:::
### About Cache
Due to the diversity of filtering conditions, KavaRef does not directly provide caching function,
and the implementation method of caching will also vary depending on the implementation method of each developer.
We recommend manually implementing caches of `MemberResolver` created with filter results for improved performance
and refer to [Create Manually](#create-manually) to split filter conditions to optimize code reuse.
::: danger
If you use `val myResolver by lazy { ... }` to implement the cache, for example, do so below.
> The following example
```kotlin
val myResolver by lazy {
Test::class.resolve()
.firstMethod {
name = "doTask"
parameters(String::class)
}
}
```
You may do this when calling.
> The following example
```kotlin
// Suppose this is an instance of this Class.
val test: Test
// Call and execute using KavaRef.
myResolver.of(test).invoke("task_name")
```
Please note that since `MemberResolver` is cached, the same instance is called every time you reference it,
and the instance object of `MemberResolver` is not allowed to be set duplicately (see the "Pay Attention" below [Create Manually](#create-manually)).
So calling this directly will throw an exception, you need to change it to the following form.
> The following example
```kotlin
// Suppose this is an instance of this Class.
val test: Test
// Call and execute using KavaRef.
myResolver.copy().of(test).invoke("task_name")
```
This allows you to copy a new `MemberResolver` instance every time you call without repeating the reflection process and throwing an exception.
:::
### Java Usage
KavaRef is not recommended to be used directly in Java because its API design is based on Kotlin's features and syntax sugar.
If you need to use KavaRef in Java, you can do it in the following ways.
> The following example
```java
public class Main {
public static void main(String[] args) {
// Suppose this is an example of this Class.
Test test;
// Call and execute with KavaRef.
KavaRef.resolveClass(Test.class)
.method()
.name("doTask")
.parameters(String.class)
.build()
.get(0)
.of(test)
.invoke("task_name");
// Or create KavaRef reflections using an instance.
KavaRef.resolveObject(test)
.method()
.name("doTask")
.parameters(String.class)
.build()
.get(0)
.invoke("task_name");
}
}
```

View File

@@ -0,0 +1,315 @@
# kavaref-extension
![Maven Central](https://img.shields.io/maven-central/v/com.highcapable.kavaref/kavaref-extension?logo=apachemaven&logoColor=orange&style=flat-square)
<span style="margin-left: 5px"/>
![Maven metadata URL](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fraw.githubusercontent.com%2FHighCapable%2Fmaven-repository%2Frefs%2Fheads%2Fmain%2Frepository%2Freleases%2Fcom%2Fhighcapable%2Fkavaref%2Fkavaref-extension%2Fmaven-metadata.xml&logo=apachemaven&logoColor=orange&label=highcapable-maven-releases&style=flat-square)
This is an extended dependency for KavaRef-related features.
## Configure Dependency
You can add this module to your project using the following method.
### SweetDependency (Recommended)
Add dependency in your project's `SweetDependency` configuration file.
```yaml
libraries:
com.highcapable.kavaref:
kavaref-extension:
version: +
```
Configure dependency in your project `build.gradle.kts`.
```kotlin
implementation(com.highcapable.kavaref.kavaref.extension)
```
### Version Catalog
Add dependency in your project's `gradle/libs.versions.toml`.
```toml
[versions]
kavaref-extension = "<version>"
[libraries]
kavaref-extension = { module = "com.highcapable.kavaref:kavaref-extension", version.ref = "kavaref-extension" }
```
Configure dependency in your project `build.gradle.kts`.
```kotlin
implementation(libs.kavaref.extension)
```
Please change `<version>` to the version displayed at the top of this document.
### Traditional Method
Configure dependency in your project `build.gradle.kts`.
```kotlin
implementation("com.highcapable.kavaref:kavaref-extension:<version>")
```
Please change `<version>` to the version displayed at the top of this document.
## Function Introduction
You can view the KDoc [click here](kdoc://kavaref-extension).
### Class Extensions
KavaRef provides some extensions that are more convenient when dealing with `Class` objects.
KavaRef also adds the `KClass` extensions to the `Class` extensions,
which is used to call `KClass.java`, which is more concise than using `Some::class.java` directly.
#### Create Class Object
For example, we need to create a `Class` object using the string class name.
> The following example
```kotlin
val myClass = "com.example.MyClass".toClass()
// You can use a method with OrNull suffix to return null
// when Class is not found instead of throwing an exception.
val myClassOrNull = "com.example.MyClass".toClassOrNull()
```
These methods use `ClassLoaderProvider` to get the default `ClassLoader`,
you can set the default `ClassLoader` to affect global functionality.
> The following example
```kotlin
ClassLoaderProvider.classLoader = MyCustomClassLoader()
```
You can also manually pass a `ClassLoader` parameter to the `toClass` method to specify which `ClassLoader` to use.
#### Class Object Reference
Referring to Java Class in Kotlin requires writing a very long statement,
such as `MyClass::class.java`, which you can simplify in the following ways.
> The following example
```kotlin
val myClass = classOf<MyClass>()
```
You can use the `isSubclassOf` method to determine whether a `Class` is another `Class` subclass.
> The following example
```kotlin
val isSubclass = MyClass::class isSubclassOf MySuperClass::class
// Of course, it also has a corresponding antonym of judgment.
val isNotSubclass = MyClass::class isNotSubclassOf MySuperClass::class
```
You can also use the `hasSuperclass` and `hasInterfaces` methods to determine whether a `Class` has a superclass or an interface.
::: danger
The `Class` passed in by the `classOf` method will perform unboxing of Java wrapper classes by default,
whether you pass in something like `kotlin.Boolean` or `java.lang.Boolean` (see [Java Wrapper Classes Extensions](#java-wrapper-classes-extensions) below),
If you need to avoid the incoming `Class` being unboxed into primitive types, you need to explicitly set the `primitiveType = false` parameter.
:::
#### Create New Instance
KavaRef provides a way for `Class` to easily create a new instance.
You don't need to consider the type of constructing parameters,
you just need to pass in the corresponding parameters to create a new instance immediately.
> The following example
```kotlin
val myClass = MyClass::class.createInstance("Hello", 123)
// You can also use a method with the OrNull suffix to return null
// when creation fails instead of throwing an exception.
val myClassOrNull = MyClass::class.createInstanceOrNull("Hello", 123)
// The createInstance method only filters public constructors by default.
// If you need to call non-public constructors, please set isPublic = false.
val myClassWithPrivateConstructor = MyClass::class.createInstance("Private!", isPublic = false)
// If you want to specify the type to create an instance to use another type,
// you can use the following method.
val mySuperClass = MyClass::class.createInstanceAsType<MySuperClass>("Hello", 123)
// Similarly, you can use a method with the OrNull suffix to return null when
// creation fails instead of throwing an exception.
val mySuperClassOrNull = MyClass::class.createInstanceAsTypeOrNull<MySuperClass>("Hello", 123)
```
::: tip
After the `createInstance` method is successfully matched once, it will cache the results to prevent performance losses
caused by duplicated reflections. It is thread-safe and you can use it in any standard scenario with confidence.
:::
::: danger
When you pass in a parameter with `null`, KavaRef tries to use it as part of the matchable condition (vague condition), and the accuracy may decrease.
The `createInstance` method does not allow all parameters to be `null` (the conditions are completely vague),
and an exception will be thrown directly because this situation cannot be determined which instance to create.
:::
#### Class Modifier
KavaRef also extends `Modifier`, you can directly use `Class.isPublic` and other methods to judge a `Class` modifier.
#### VariousClass
KavaRef provides the `VariousClass` class to load the `Class` object with an indeterminate full class name and return the first match successfully.
This feature is usually used for class names in Android apps that are obfuscated by R8.
> The following example
```kotlin
// Assume that in version A, this class is com.example.a,
// In version B, this class is com.example.b.
val myClass = VariousClass("com.example.a", "com.example.b").load()
// You can also use a method with the suffix OrNull to return null
// instead of throwing an exception if Class is not found.
val myClassOrNull = VariousClass("com.example.a", "com.example.b").loadOrNull()
```
#### Lazy Loading Class Object
KavaRef provides the `LazyClass` class to lazy loading the `Class` object.
You can load `Class` when needed, instead of loading it immediately when created,
which can solve some `Class` that need to be loaded when run or run to specific conditions.
> The following example
```kotlin
// Define a Class that cannot be loaded for null and hosts it to myClass.
val myClass by lazyClass("com.example.MyClass")
// Define a Class that can be loaded for null delay and host it to myClassOrNull.
val myClassOrNull by lazyClassOrNull("com.example.MyClass")
// It can also support incoming VariousClass.
val otherClassOrNull by lazyClassOrNull(VariousClass("com.example.a", "com.example.b"))
// Called and loaded when needed.
myClass.resolve()
myClassOrNull?.resolve()
otherClassOrNull?.resolve()
```
#### ClassLoader Extensions
KavaRef also provides some practical extension methods for `ClassLoader`.
> The following example
```kotlin
// Assume that's your ClassLoader.
val classLoader: ClassLoader
// Load a Class and return null if the load fails.
val myClassOrNull = classLoader.loadClassOrNull("com.example.MyClass")
// Determine whether this Class exists in the current ClassLoader.
val isClassExists = classLoader.hasClass("com.example.MyClass")
```
### Array Class Extensions
In Java, the `Class` object of an array is a special `Class` object, and usually we create it as follows.
For example, create a `Class` object of `java.lang.String[]`.
> The following example
```kotlin
val arrayClass = java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
```
This is very long to write and is not convenient to maintain, so KavaRef provides a way to simplify this process.
Now, the `Class` object that creates `java.lang.String[]` can be written like this.
> The following example
```kotlin
val arrayClass = ArrayClass(String::class)
```
### Member Extensions
KavaRef provides some extension methods to simplify operations on `Member`.
You can set its accessibility using the `makeAccessible` method on any `Member` object.
It will take effect if `Member` is the `AccessibleObject` type.
> The following example
```kotlin
// Suppose this is your current Member object.
val method: Method
// Make method is accessible.
method.makeAccessible()
```
Similarly, KavaRef also extends `Modifier`, and you can directly use `Member.isPublic` and other methods to judge a `Member` modifier.
### Type Extensions
When manipulating types or generic types in Java, you usually need to use the `Type` interface and its subinterface to handle it.
KavaRef provides some extension methods to simplify operations on `Type`.
For example, you can convert a `Type` that meets the requirements to a `Class` object.
> The following example
```kotlin
val type: Type
val clazz = type.toClass()
// You can also use a method with the suffix named OrNull to
// return null when the conversion fails instead of throwing an exception.
val clazzOrNull = type.toClassOrNull()
```
You can also convert `Type` that meets the requirements to `ParameterizedType` object.
> The following example
```kotlin
val type: Type
val parameterizedType = type.asParameterizedType()
// You can also use a method with the suffix named OrNull to
// return null when the conversion fails instead of throwing an exception.
val parameterizedTypeOrNull = type.asParameterizedTypeOrNull()
```
You can also use the following method to get the generic parameter array in the superclass,
which is often used in some superclass and subclass encapsulation operations.
> The following example
```kotlin
val myClass: Class<*>
// Get the generic parameter array of myClass superclass.
// If the acquisition fails or cannot be retrieved, the empty array will be returned.
val arguments = myClass.genericSuperclassTypeArguments()
```
### Java Wrapper Classes Extensions
In Kotlin, you can directly use `Boolean::class`, `Byte::class`, etc. to obtain Java's original types `boolean` and `byte` instead of their wrapper classes.
If you need to get Java wrapper classes, you need to use the complete `java.lang.Boolean::class`, `java.lang.Byte::class`, etc.
or use `Boolean::class.javaObjectType`, `Byte::class.javaObjectType`.
So, KavaRef provides some type alias to handle Java wrapper classes. Now you only need to prefix `J` to these types, such as `JBoolean::class`.
It is equivalent to `java.lang.Boolean::class`, and some types need to be filled in the full name, such as `JInteger::class`.