通过 java 反射检索在静态声明的功能接口中使用的静态参数值

Retrieve static argument values used within statically declared functional interfaces via java reflection

看看我的代码:

import java.util.function.Function;

public class StaticArgumentsTest {

    static Function<String, String> staticConsumer(String testValue) {
        return (st) -> testValue + " and " + st;
    }

    static final Function<String, String> aStaticConsumer =
            staticConsumer("Static String Example Value");

    public static void main(String[] args) {
        System.out.println(StaticArgumentsTest.aStaticConsumer.apply("Dynamic String Example Value"));
    }
}

我们有一些带有许多此类功能接口实现的遗留代码,我宁愿让这些代码处于更易于管理的状态,如数据库,而不是将这些设置放在普通的 java 代码中。所以我的问题是,是否可以使用反射找到您在上面看到的字符串值 "Static String Example Value"?我可能宁愿这样做,也不愿为这些东西编写自己的 java 代码解析器,但据我所知,我一直坚持这样做。

当然,这高度依赖于实现,不推荐用于生产代码,但对于一次性转换任务,它将与普通的反射操作和 HotSpot/OpenJDK 的当前实现一起工作:

public class StaticArgumentsTest {

    static Function<String, String> staticConsumer(String testValue) {
        return (st) -> testValue + " and " + st;
    }

    static final Function<String, String> aStaticConsumer =
            staticConsumer("Static String Example Value");

    public static void main(String[] args) {
        System.out.println(aStaticConsumer.apply("Dynamic String Example Value"));
        getCapturedValues(aStaticConsumer);
    }

    private static void getCapturedValues(Object instance) {
        Field[] f = instance.getClass().getDeclaredFields();
        AccessibleObject.setAccessible(f, true);
        for(Field field: f) {
            System.out.print(field.getName()+" ("+field.getType()+"): ");
            try { System.out.println(field.get(instance)); }
            catch(ReflectiveOperationException ex) { System.out.println(ex); }
        }
    }
}
Static String Example Value and Dynamic String Example Value
arg (class java.lang.String): Static String Example Value

当然,这些合成字段没有有意义的名称,但对于只捕获一个值的 lambda 表达式,这是显而易见的,而对于其他字段,您可以使用一些合理的启发式方法,例如根据类型或顺序,找出哪个字段对应哪个变量。