昨晚我正在玩Java8 Lambda,我想知道是否可以在运行时检索Lambda表达式。简而言之,据我所知,Lambda表达式在运行时转换为(静态)方法,然后使用InvokeDynamics进行调用。
我们举个这样的例子:
people.filter(person -> person.getAge() >= minAge);
其中filter
是一个以Predicate<T>
为参数的自定义方法。
在这个filter
方法中,如何在这种情况下以与Lambda表达式(person -> person.getAge() >= minAge
)相似(或相同)的形式检索参数?
我尝试使用ASM5_BETA读取参数类的生成字节码,但我无法使用ClassVisitor和MethodVisitor来访问与Lambda表达式相关联的方法。
public <T> List<T> filter(Filter<T> expression) {
try {
Class<? extends Filter> expressionClass = expression.getClass();
byte[] content = getClassContent(expressionClass);
ClassReader classReader = new ClassReader(content);
classReader.accept(new PredicateClassVisitor(), 0);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
private byte[] getClassContent(Class<? extends Filter> expressionClazz) throws
IOException {
InputStream stream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(getClassName(expressionClazz.getName()));
return IOUtils.toByteArray(stream);
}
private String getClassName(String expressionClazz) {
return expressionClazz.substring(0, expressionClazz.indexOf('$'))
.replace('.', '/') + ".class";
}
static class PredicateClassVisitor extends ClassVisitor {
public PredicateClassVisitor() {
super(Opcodes.ASM4);
}
@Override
public MethodVisitor visitMethod(int i, String s, String s2, String s3,
String[] strings) {
return new PredicateMethodVisitor();
}
}
static class PredicateMethodVisitor extends MethodVisitor {
public PredicateMethodVisitor() {
super(Opcodes.ASM4);
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
Object... bsmArgs) {
for (Object object : bsmArgs) {
System.out.println(" " + object.toString());
}
}
}
我不确定这是正确的路径,我想知道ASM或JDK8中是否有更合适的工具用于此目的。
感谢您的任何建议;-) 最好的祝福, 泽维尔
答案 0 :(得分:4)
你已经知道lambda表达式通常被编译成一个合成方法,所以你已经知道要反编译哪些代码来获取lambda的源代码,或者,类似于原始代码的东西,甚至看起来完全不同的东西,取决于特定的代码。
没有理由反编译lambda表达式比反编译任何其他Java表达式更容易。简单表达式可能很容易恢复,特别是当代码具有调试信息时,复杂表达式在反编译时很可能看起来不同,特别是当编译器对代码应用优化时。
答案 1 :(得分:1)
在某些情况下,您可以使用Groovy执行此操作,如果这可以帮助您:Getting the contents of closure, in groovy。 Geb实际上使用此功能突出显示评估表达式中的断言错误。