我有一个方法,假设将类名,参数和方法名称作为参数,并根据它找到的类调用该方法.方法:
Method[] methods = className.getDeclaredMethods();
for (Method meth: methods) {
if (meth.getName().equalsIgnoreCase(methodName)) {
try {
MethodType mt = MethodType.methodType(boolean.class, String.class);
MethodHandles.Lookup caller = MethodHandles.lookup();
MethodHandle handle = caller.findVirtual(Utilities.class, meth.getName(), mt);
/*
* Trying to invoke using lambdaMetaFactory
*/
MethodType methodType = MethodType.methodType(boolean.class);
MethodType invokedType = MethodType.methodType(BooleanSupplier.class);
/*
* Throws java.lang.invoke.LambdaConversionException: Incorrect number of parameters for instance method
* invokeVirtual com.grainger.Automation.Utilities.navigateToUrl:(String)boolean; 0 captured parameters,
* 0 functional interface method parameters, 1 implementation parameters
*/
CallSite site = LambdaMetafactory.metafactory(caller, "getAsBoolean", invokedType, methodType, handle, methodType);
MethodHandle factory = site.getTarget();
BooleanSupplier r = (BooleanSupplier) factory.invoke();
System.out.println(r.getAsBoolean());
/*
* Trying to invoke using Method Handle
*/
/*
* Trying to invoke the method handle here, but it fails with:
* java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(Utilities,String)boolean to (Object)Object
* methodArguments is an ArrayList<> that is initialized and populated before
*/
System.out.println(handle.invokeWithArguments(methodArguments.toArray())); //Output B
/*
* Invoking it directly with a string as an argument throws this execption:
* com.sun.jdi.InvalidTypeException: Generated value (java.lang.String) is not compatible with declared type (java.lang.Object[]). occurred invoking method.
*/
System.out.println(handle.invokeExact("www.google.com"));
// keywordResult = (Boolean) handle.invoke("www.google.com");
/*
* Using the regular Reflections API, the method invoke works but is slow
*/
// keywordResult = (Boolean) meth.invoke(classInstance, methodArguments); //Regular refection call to invoke the function
break;
} catch (Throwable e) {
System.out.println(e.getMessage());
keywordResult = false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我试图调用的方法位于同一个包中的一个单独的类中.这是方法定义:
public boolean navigateToUrl(String strUrl) {
return true;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试使用lambdametafactory调用该函数时,我得到一个LambdaConversionException.当我尝试使用方法句柄调用该方法时,在使用参数调用并发送ArrayList <>时,我得到异常Java.lang.invoke.WrongMethodTypeException.当使用String作为参数执行invokExact时,我得到一个com.sun.jdi.InvalidTypeException.所有这些也在评论中列出.
我无法弄清楚我在这里做错了什么.任何帮助将不胜感激!如果他们是我在代码中遗漏的任何内容,请告诉我!
通过一个方法调用一个方法MethodHandle通常分4个步骤:
MethodHandles.Lookup负责创建的查找对象MethodHandle;MethodType表示方法句柄接受并返回的参数类和返回类型类;MethodHandle查找和MethodType给定的类;MethodHandle使用一些参数调用.例如,假设您要调用该方法
public boolean navigateToUrl(String strUrl) {
return true;
}
Run Code Online (Sandbox Code Playgroud)
位于课堂上FooBar.
public void invokeMethod() throws Throwable {
// 1. Retrieves a Lookup
MethodHandles.Lookup lookup = MethodHandles.lookup();
// 2. Creates a MethodType
MethodType methodType = MethodType.methodType(boolean.class, String.class);
// ^-----------^ ^----------^
// return type argument class
// 3. Find the MethodHandle
MethodHandle handle = lookup.findVirtual(FooBar.class, "navigateToUrl", methodType);
// ^----------^ ^-------------^
// | name of method
// class from which method is accessed
// 4. Invoke the method
boolean b = (boolean) handle.invokeExact(fooBar, "test");
// ^----^ ^----^
// | argument
// instance of FooBar to invoke the method on
System.out.println(b);
}
Run Code Online (Sandbox Code Playgroud)
这是一个示例代码:
publicLookup().您可以参考这个问题 (和这一个),了解更多有关什么MethodHandles为.
| 归档时间: |
|
| 查看次数: |
1987 次 |
| 最近记录: |