当前位置: 首页 > 面试题库 >

是否可以在运行时检索lambda表达式

谭光辉
2023-03-14
问题内容

昨晚我在玩Java8
Lambda,我想知道是否有可能在运行时检索Lambda表达式。简而言之,据我所知,Lambda表达式在运行时被转换为(静态)方法,然后使用InvokeDynamics进行调用

让我们举一个这样的例子:

people.filter(person -> person.getAge() >= minAge);

其中filter将是以a
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中是否有更合适的工具来实现这一目的。

感谢您的任何建议;-)最好的问候,Xavier


问题答案:

您已经知道lambda表达式通常会编译为合成方法,因此您已经知道要反编译哪些代码以获取lambda的源代码,或者,类似于原始代码的东西,或者甚至看起来完全不同的东西,具体取决于特定的代码。

没有理由比反编译任何其他Java表达式容易地反编译lambda表达式。简单表达式可能易于恢复,尤其是当代码具有调试信息时,复杂表达式在反编译时很可能看起来会有所不同,尤其是在编译器对代码进行优化时。



 类似资料:
  • 问题内容: 具体来说,我有TabPane,我想知道其中是否包含具有特定ID的元素。 因此,我想使用Java中的lambda表达式来做到这一点: 问题答案: 尝试使用Lambda表达式。这是更好的方法。

  • 具体来说,我有TabPane,我想知道其中是否有具有特定ID的元素。 所以,我想用Java中的lambda表达式来实现这一点:

  • 问题内容: 例如,假设我想“提取” 为三个单独的变量,例如: 我该怎么做,而忽略了 “为什么要这么做呢?” 您可能会被问到这个问题。 之前已经多次问过类似的问题,但是从未给出真正的答案,因为OP真正需要的是使用不同的方法。很好,但这有可能吗? 我看过反射,似乎没有任何方法可以使我甚至向实例添加额外的字段,更不用说动态创建本地了。 问题答案: 是否可以在Java运行时创建变量? 简单回答是不。 Ja

  • 问题内容: 我正在一个项目中,该项目有很多由库创建的对象,并且无法访问这些对象的创建过程。 以下代码片段很好地说明了我的问题。 码: 是Clazz在编译时可能会或可能不会实现的接口。 码: 以下代码是我遇到的问题。请注意以下几点: 仅在c是的实例时调用。 并且都是我无法访问的类中的私有方法。 在编译时,将 不 包含名为的方法。 ExampleExecutor 不是 我的课程。我无法以任何方式访问它

  • 问题内容: 所以…例如,我正在尝试将一个电子邮件“模板”引入iframe中,作为angularjs应用程序内用户的“预览”。iframe位于控制器区域内(我们称其为MainCtrl)。然后,用户将能够使用MainCtrl内提供的表单元素基于其输入来更新预览。举例来说,假设我们将模板拉入iframe的过程如下所示: 因此,在我们的index.html(angularjs应用)中,我们将具有绑定到{{

  • 是否可以通过用lambda表达式或其他类的非静态方法替换执行来拦截方法? 例1: 其目的是避免使用静态方法编写类来执行拦截。 例2: 此代码段不代表完整的场景。它只是为了举例说明这个问题。 截取公共方法可以通过其他方式完成,但目标不是仅使用公共方法,或仅使用测试场景。