我正在尝试使用 LambdaMetafactory 来替换反射,但我有一个问题。如果我使用特定的类,那么它工作得很好,就像这样:
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType type = MethodType.methodType(ResponseMsg.class,Map.class);
MethodHandle mh = lookup.findVirtual(TestService.class,"testMethod",type);
TestService ins = TestService.getInstance();
MethodHandle factory = LambdaMetafactory.metafactory(
lookup, "apply", MethodType.methodType(Function.class,TestService.class),
type.generic(), mh, type).getTarget();
factory.bindTo(ins);
Function lambda = (Function) factory.invokeExact(ins);
但是如果我Class<?>
用来替换特定的类,那么它就不起作用了,就像这样:
public static Function generateLambda(@NotNull Class<?> cls,@NotNull String method) {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType type = MethodType.methodType(RETURN_TYPE,PARM_TYPE);
try {
MethodHandle mh = lookup.findVirtual(cls,method,type);
Object instance = getInstance(cls);
if(instance == null) {
return null;
}
MethodHandle factory = LambdaMetafactory.metafactory(
lookup, "apply", MethodType.methodType(Function.class,cls),
type.generic(), mh, type).getTarget();
factory.bindTo(cls.cast(instance));
return (Function) factory.invokeExact(cls.cast(instance));
} catch (Throwable e) {
logger.error("get Function fail, cause :" ,e);
return null;
}
}
这是一个例外:
java.lang.invoke.WrongMethodTypeException: expected (TestService)Function but found (Object)Function
at java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:298)
at java.lang.invoke.Invokers.checkExactType(Invokers.java:309)
at com.utils.cache.ClassUtils.generateLambda(ClassUtils.java:182)
第 182 行是:
return (Function) factory.invokeExact(cls.cast(instance));
我知道只使用静态方法可以解决这个问题,但我想知道有没有其他方法可以在不将非静态更改为静态的情况下解决它。
这是getInstance:
private static Object getInstance(@NotNull Class<?> cls) {
try {
Method getInstanceMethod = cls.getDeclaredMethod("getInstance");
return getInstanceMethod.invoke(null);
} catch (Exception e) {
logger.error("get instance fail, cause :" ,e);
return null;
}
}
在这个方法中,我使用反射在Class中找到静态方法getInstance,并返回一个实例,它只是一个简单的单例。