使用 MethodHandles 调用编译时未知的 class 的方法(无反射)
Using MethodHandles to call a method on of class that isn't known at compile time (without reflection)
我需要调用 Person
class 的 getName()
方法,而不知道 Person
class 作为编译时间并使用 MethodHandle (而不是正常反射)。
所以我希望此代码能够工作(此代码无法更改):
MyGetterAccessor myGA = new MyGetterAccessor(Person.class, "getName", String.class)
assertEquals("Ann", myGA.call(new Person("Ann"));
assertEquals("Beth", myGA.call(new Person("Beth"));
这是我的方法句柄代码,它不能使用单词 "Person"(可以更改以使其工作):
public class MyGetterAccessor {
MethodHandle mh;
public GetterAccessor(Class entityClass, String methodName, Class returnType) {
mh = MethodHandles.lookup().findVirtual(entityClass, methodName, MethodType.methodType(returnType));
}
public Object call(Object entity) {
return mh.invokeExact(entity);
}
}
但这失败了WrongMethodTypeException
。有什么解决方法的建议吗?
可能
public static <T,R> setValue(T setTo, BiFunction<T,String,R> setter, String value) {
return setter.apply(setTo, value);
}
assertEquals("Ann", setValue(new Person(), Person::set, "Ann"));
还是反射不够?
FWIW,这有效,但是 it's slow in java 8 in my benchmarks。
MethodHandle temp = lookup.findVirtual(getterMethod.getDeclaringClass(), getterMethod.getName(), MethodType.methodType(returnType));
temp = temp.asType(temp.type().changeParameterType(0 , Object.class));
getterMethodHandle = temp.asType(temp.type().changeReturnType(Object.class));
我需要调用 Person
class 的 getName()
方法,而不知道 Person
class 作为编译时间并使用 MethodHandle (而不是正常反射)。
所以我希望此代码能够工作(此代码无法更改):
MyGetterAccessor myGA = new MyGetterAccessor(Person.class, "getName", String.class)
assertEquals("Ann", myGA.call(new Person("Ann"));
assertEquals("Beth", myGA.call(new Person("Beth"));
这是我的方法句柄代码,它不能使用单词 "Person"(可以更改以使其工作):
public class MyGetterAccessor {
MethodHandle mh;
public GetterAccessor(Class entityClass, String methodName, Class returnType) {
mh = MethodHandles.lookup().findVirtual(entityClass, methodName, MethodType.methodType(returnType));
}
public Object call(Object entity) {
return mh.invokeExact(entity);
}
}
但这失败了WrongMethodTypeException
。有什么解决方法的建议吗?
可能
public static <T,R> setValue(T setTo, BiFunction<T,String,R> setter, String value) {
return setter.apply(setTo, value);
}
assertEquals("Ann", setValue(new Person(), Person::set, "Ann"));
还是反射不够?
FWIW,这有效,但是 it's slow in java 8 in my benchmarks。
MethodHandle temp = lookup.findVirtual(getterMethod.getDeclaringClass(), getterMethod.getName(), MethodType.methodType(returnType));
temp = temp.asType(temp.type().changeParameterType(0 , Object.class));
getterMethodHandle = temp.asType(temp.type().changeReturnType(Object.class));