Skip to content

Commit

Permalink
Added methods simpleCall(), simpleSet() and callWithClass
Browse files Browse the repository at this point in the history
  • Loading branch information
zeshaoaaa committed Jul 11, 2019
1 parent 585f7e2 commit 34dd1b4
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 20 deletions.
43 changes: 41 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,36 @@ val str = OkReflect



### 11. Simply set field or call method
### 11. Call method with class info

```java
// Java
Class classes[] = {String.class, Byte.class};
Object args[] = {"Tom", null};
String name = OkReflect.on(TestClass.class)
.create()
.callWithClass("setData2", classes, args)
.get("name");
```

```kotlin
// Kotlin
val classes = arrayOf<Class<*>>(String::class.java, Byte::class.javaObjectType)
val args = arrayOf<Any?>("Tom", null)
val name = OkReflect.on(TestClass::class.java)
.create()
.callWithClass("setData2", classes, *args)
.get<String?>("name")
```





### 12. Simply set field or call method

```java
// Java
TestClass testClass = new TestClass();
String nameFromeMethod = OkReflect.on(testClass)
.simpleCall("getName");
Expand All @@ -225,9 +252,19 @@ String name = OkReflect.on(testClass)
.simpleSet("name", "Tom");
```

```kotlin
// Kotlin
val testClass = TestClass()
val nameFromMethod = OkReflect.on(testClass)
.simpleCall<String>("getName")

val name = OkReflect.on(testClass)
.simpleSet<String>("name", "Tom")
```



### 12. Use dynamic proxy
### 13. Use dynamic proxy

```Java
// First step of using dynamic proxy: declare the interface
Expand All @@ -254,6 +291,8 @@ val substring = OkReflect.on("java.lang.String")

###



## Configuration
### Gradle
```groovy
Expand Down
48 changes: 46 additions & 2 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

OkReflect 是一个封装了 Java 反射操作的工具。

[OkReflect 介绍](https://www.jianshu.com/p/7ffc22eee6cc)

## 用法

### 1. 使用类名创建类
Expand Down Expand Up @@ -211,9 +213,38 @@ val str = OkReflect
.get<String>()
```

### 11. 只修改字段或调用方法


### 11. 调用方法并传入实参类型信息

```java
// Java
Class classes[] = {String.class, Byte.class};
Object args[] = {"Tom", null};
String name = OkReflect.on(TestClass.class)
.create()
.callWithClass("setData2", classes, args)
.get("name");
```

```kotlin
// Kotlin
val classes = arrayOf<Class<*>>(String::class.java, Byte::class.javaObjectType)
val args = arrayOf<Any?>("Tom", null)
val name = OkReflect.on(TestClass::class.java)
.create()
.callWithClass("setData2", classes, *args)
.get<String?>("name")
```





### 12. 纯设置字段或调用方法

```java
// Java
TestClass testClass = new TestClass();
String nameFromeMethod = OkReflect.on(testClass)
.simpleCall("getName");
Expand All @@ -222,8 +253,21 @@ String name = OkReflect.on(testClass)
.simpleSet("name", "Tom");
```

```kotlin
// Kotlin
val testClass = TestClass()
val nameFromMethod = OkReflect.on(testClass)
.simpleCall<String>("getName")

val name = OkReflect.on(testClass)
.simpleSet<String>("name", "Tom")
```





### 12. 动态代理
### 13. 动态代理

```Java
// First step of using dynamic proxy: declare the interface
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/okreflect/MethodCall.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package okreflect
class MethodCall(val methodName: String,
var classes: Array<Class<*>>?,
val callWithInstance: Boolean,
val args: Array<out Any>)
val args: Array<out Any?>)
6 changes: 3 additions & 3 deletions src/main/kotlin/okreflect/OkReflect.kt
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,15 @@ class OkReflect {
* The method will be called when [get] method called.
* The method will be call with the instance.
*/
fun call(methodName: String, classes: Array<Class<*>>?, vararg args: Any): OkReflect {
fun callWithClass(methodName: String, classes: Array<Class<*>>?, vararg args: Any?): OkReflect {
return realCall(true,methodName, classes, *args)
}

/**
* @See [call]
*/
fun call(methodName: String, vararg args: Any): OkReflect {
return call(methodName, null, *args)
return callWithClass(methodName, null, *args)
}

/**
Expand Down Expand Up @@ -228,7 +228,7 @@ class OkReflect {
callWithInstance: Boolean = true,
methodName: String,
classes: Array<Class<*>>?,
vararg args: Any
vararg args: Any?
): OkReflect {
if (methodCallList == null) {
methodCallList = ArrayList()
Expand Down
6 changes: 3 additions & 3 deletions src/test/java/UseCaseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ public void testCallMethodWithVoidParameter() {
Object args[] = {"Tom", null};
String name = OkReflect.on(TestClass.class)
.create()
.call("setData2", classes, args)
.callWithClass("setData2", classes, args)
.get("name");
assert name.equals("Tom");
}
Expand All @@ -254,8 +254,8 @@ public void testCallMethodsWithVoidParameter() {
Object args2[] = {"Bingo", null};
TestClass instance = OkReflect.on(TestClass.class)
.create()
.call("setData2", classes1, args1)
.call("setData3", classes2, args2)
.callWithClass("setData2", classes1, args1)
.callWithClass("setData3", classes2, args2)
.get();

String name = OkReflect.on(instance)
Expand Down
107 changes: 98 additions & 9 deletions src/test/kotlin/KotlinUseCaseTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import org.junit.rules.ExpectedException

import java.lang.invoke.MethodHandle
import java.lang.invoke.MethodHandles
import java.lang.reflect.Field
import java.lang.reflect.Method


Expand All @@ -15,8 +14,6 @@ import java.lang.reflect.Method
*/
class KotlinUseCaseTest {

internal var expectedException = ExpectedException.none()

@Test
fun testCreateClassWithClassName() {
val str = OkReflect.on("java.lang.String")
Expand All @@ -34,12 +31,13 @@ class KotlinUseCaseTest {
}

@Test
fun testGetFieldFromSuperClass() {
val testClass = TestClass("Alex")
fun testSetAndGetFieldFromSuperClass() {
val testClass = TestClass()
val superName = OkReflect.on(SuperTestClass::class.java)
.with(testClass)
.set("superName", "Tom")
.get<String>("superName")
assert(superName == "Alex")
assert(superName == "Tom")
}

@Test
Expand All @@ -50,6 +48,8 @@ class KotlinUseCaseTest {
Assert.assertTrue(name == "Tom")
}

internal var expectedException = ExpectedException.none()

@Test(expected = NullPointerException::class)
fun testNotCallCreateException() {
val str = OkReflect
Expand Down Expand Up @@ -90,13 +90,16 @@ class KotlinUseCaseTest {
Assert.assertEquals(str, "Hello world")
}

// 10. Handle the exception with callback
@Test
fun testNotCallCreateErrorCallback() {
val str = OkReflect
.on("java.lang.String")
.error {
assert(it.toString().contains("you have to call create()"))
}
.error(object : OkReflect.OkReflectErrorCallback {
override fun onError(e: Exception) {
assert(e.toString().contains("you have to call create()"))
}
})
.get<String>()
}

Expand Down Expand Up @@ -172,6 +175,7 @@ class KotlinUseCaseTest {
assert(clazz == TestClass::class.java)
}

// 9. Get and set static field value of the class
@Test
fun testSetStaticField() {
val finalField = OkReflect.on("TestClass")
Expand Down Expand Up @@ -227,6 +231,61 @@ class KotlinUseCaseTest {
assert(name == "Tom")
}

@Test
fun testCallMethodWithVoidParameter() {
val classes = arrayOf<Class<*>>(String::class.java, Byte::class.javaObjectType)
val args = arrayOf<Any?>("Tom", null)
val name = OkReflect.on(TestClass::class.java)
.create()
.callWithClass("setData2", classes, *args)
.get<String?>("name")
assert(name == "Tom")
}

@Test
fun testCallMethodsWithVoidParameter() {
val classes1 = arrayOf<Class<*>>(String::class.java, Byte::class.java)
val classes2 = arrayOf<Class<*>>(String::class.java, Char::class.java)
val args1 = arrayOf<Any?>("Tom", null)
val args2 = arrayOf<Any?>("Bingo", null)
val instance = OkReflect.on(TestClass::class.java)
.create()
.callWithClass("setData2", classes1, *args1)
.callWithClass("setData3", classes2, *args2)
.get<TestClass>()

val name = OkReflect.on(instance!!)
.get<String>("name")
val nickname = OkReflect.on(instance!!)
.get<String>("nickname")

assert(name == "Tom" && nickname == "Bingo")
}

@Test
fun testGetResult() {
val testClass = TestClass()
val name = OkReflect.on(testClass)
.call("getName")
.getResult<String>()
assert(name == "default")
}

@Test
fun testSimpleCall() {
val testClass = TestClass()
val name = OkReflect.on(testClass)
.simpleCall<String>("getName")
assert(name == "default")
}

@Test
fun testSimpleSet() {
val testClass = TestClass()
val name = OkReflect.on(testClass)
.simpleSet<String>("name", "Tom")
assert(name == "Tom")
}

@Ignore
@Test
Expand All @@ -237,5 +296,35 @@ class KotlinUseCaseTest {
assert(finalField == "changed")
}

@Ignore
@Test
fun testChangeParameterTypeByMethodHandle() {
val originTypes = arrayOf<Class<*>>(String::class.java, Char::class.java)
val newTypes = arrayOf<Class<*>>(String::class.java, Char::class.java)
try {
val method = TestClass::class.java.getDeclaredMethod("setData3", *originTypes)
method.isAccessible = true
val methodHandle = MethodHandles.lookup().unreflect(method)
val filter = getFilter(originTypes, newTypes)
MethodHandles.filterArguments(methodHandle, 2, filter)
println("")
} catch (e: NoSuchMethodException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
}

}

@Throws(IllegalAccessException::class, NoSuchMethodException::class)
private fun getFilter(originTypes: Array<Class<*>>, newTypes: Array<Class<*>>): MethodHandle {
var filterMethod: Method? = TestClass::class.java.getDeclaredMethod("setData3", *originTypes)
filterMethod = OkReflect.on(filterMethod!!)
.set("parameterTypes", newTypes)
.get<Method>()
filterMethod!!.isAccessible = true
return MethodHandles.lookup().unreflect(filterMethod)
}


}

0 comments on commit 34dd1b4

Please sign in to comment.