Kin*_*ung 4 java reflection lambda
在 JDK 8 中,我可以使用反射来调用带有 FunctionInterface 参数的方法,并传递 Lambda 表达式。例如,这有效。
import java.util.function.IntPredicate;
import java.lang.reflect.Method;
public class LambdaReflect {
public static void main(String args[]) {
System.out.println(test(x->true));
// Now do this in reflection
Class<LambdaReflect> thisC = LambdaReflect.class;
Method meths[] = thisC.getDeclaredMethods();
Method m = meths[1]; // test method
try {
IntPredicate lamb = x->true;
boolean result = (Boolean) m.invoke(null, lamb);
System.out.println(result);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static boolean test(IntPredicate func) {
return func.test(1);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果参数类型仅在运行时已知,如何将 lambda 表达式传递给该方法?换句话说,如果我在编译时不知道方法的参数类型,而只知道它是一个函数式接口,我可以使用反射用lambda表达式来调用它吗?
您可以在编译时不知道目标类型的情况下创建 lambda 表达式。但是您可以将 lambda\xe2\x80\x99s 代码放入方法中,并创建对此方法的方法引用。这类似于 lambda 表达式的编译方式。不同之处在于,函数式接口实现是使用反射代码显式创建的:
\n\nimport java.lang.invoke.*;\nimport java.util.function.IntPredicate; \nimport java.lang.reflect.Method;\n\npublic class LambdaReflect {\n\n public static void main(String args[]) {\n try {\n for(Method m: LambdaReflect.class.getDeclaredMethods()) {\n if(!m.getName().equals("test")) continue;\n // we don\xe2\x80\x99t know the interface at compile-time:\n Class<?> funcInterface=m.getParameterTypes()[0];\n // but we have to know the signature to provide implementation code:\n MethodType type=MethodType.methodType(boolean.class, int.class);\n MethodHandles.Lookup l=MethodHandles.lookup();\n MethodHandle target=l.findStatic(LambdaReflect.class, "lambda", type);\n Object lambda=LambdaMetafactory.metafactory(l, "test",\n MethodType.methodType(funcInterface), type, target, type)\n .getTarget().invoke();\n boolean result = (Boolean) m.invoke(null, lambda);\n System.out.println(result);\n break;\n }\n } catch (Throwable ex) {\n ex.printStackTrace();\n }\n }\n\n private static boolean lambda(int x) { return true; }\n\n public static boolean test(IntPredicate func) {\n return func.test(1);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n如果您想实现任意功能签名(这意味着实现相当简单,不依赖于未知参数),您可以使用MethodHandleProxies. 不同之处在于,MethodHandle不需要直接表示,即不需要表示真正的方法。因此,您可以创建一个始终返回常量的句柄,并用于dropArguments插入其他形式参数,直到您拥有一个具有正确功能签名的句柄,您可以将其传递给asInterfaceInstance
| 归档时间: |
|
| 查看次数: |
2444 次 |
| 最近记录: |