Java 创建lambda表达式的字符串表示形式

Java 创建lambda表达式的字符串表示形式,java,lambda,tostring,java-8,predicates,Java,Lambda,Tostring,Java 8,Predicates,出于调试目的,我尝试在Java8中创建lambda表达式的字符串表示(特别是谓词s的字符串表示,尽管对于其他lambda表达式也很有趣)。我的想法是这样的: public class Whatever { private static <T> String predicateToString(Predicate<T> predicate) { String representation = ... // do magic retu

出于调试目的,我尝试在Java8中创建lambda表达式的字符串表示(特别是
谓词
s的字符串表示,尽管对于其他lambda表达式也很有趣)。我的想法是这样的:

public class Whatever {

    private static <T> String predicateToString(Predicate<T> predicate) {
        String representation = ... // do magic
        return representation;
    }

    public static void main(String[] args) {
        System.out.println(Whatever.<Integer>predicateToString(i -> i % 2 == 0));
    }

}
公共类{
私有静态字符串谓词字符串(谓词谓词){
字符串表示法=…//domagic
回报代表;
}
公共静态void main(字符串[]args){
System.out.println(Whatever.predicateToString(i->i%2==0));
}
}
输出将是
i->i%2==0
(或逻辑上等价的东西)。
toString()
方法似乎没有帮助,输出类似于
com.something.Whatever$$Lambda$1/1919892312@5e91993f
(我想应该是
toString()
未被覆盖)


我不确定这样的事情是否可能发生,例如,通过反射,到目前为止我肯定还没有找到任何关于它的东西。有什么想法吗?

我能想到的最简单的事情就是创建一个“命名谓词”,为谓词提供一个名称或描述,基本上是任何有用的
toString

public class NamedPredicate<T> implements Predicate<T> {
    private final String name;
    private final Predicate<T> predicate;

    public NamedPredicate(String name, Predicate<T> predicate) {
        this.name = name;
        this.predicate = predicate;
    }

    @Override
    public boolean test(T t) {
        return predicate.test(t);
    }

    @Override
    public String toString() {
        return name;
    }

    public static void main(String... args) {
        Predicate<Integer> isEven = new NamedPredicate<>("isEven", i -> i % 2 == 0);
        System.out.println(isEven); // prints isEven
    }
}
一个奇怪的想法可能是推导谓词的“结构”描述,即某些给定输入的输出是什么?显然,当输入集是有限的和小的(例如,对于枚举、布尔或其他一些受限集)时,这将最有效,但我想您也可以尝试使用一组小的“随机”整数作为整数谓词:

private static Map<Boolean, List<Integer>> testPredicate(Predicate<Integer> predicate) {
    return Stream.of(-35, -3, 2, 5, 17, 29, 30, 460)
            .collect(Collectors.partitioningBy(predicate));
}
私有静态映射testPredicate(谓词谓词){
回流流量-35、-3、2、5、17、29、30、460)
.collect(收集器.partitionby(谓词));
}

对于
isEven
,这将返回类似
{false=[-35,-3,5,17,29],true=[2,30,460]}
,我认为这并不一定比手动给它们一个描述更清楚,但对于不受您控制的谓词可能有用。

调试目的?你不能只看源代码吗?那需要一个反编译器。@SotiriosDelimanolis当然我可以一直看源代码。但是如果有一个可打印的表示形式就好了。那你就不能复制源代码吗?@jeroenvanevel你的意思是每次手动编写一个字符串表示形式吗?可能,当然。但不是很优雅。虽然这应该可以工作,但lambda表达式语法的美妙之处在这里部分消失了,因为包装器对象
NamedPredicate
必须使用
new
操作符创建。@blalasaadri True。我想你可以通过制作一个静态工厂方法来隐藏一些丑陋的东西,比如
new
(参见所有番石榴收集工厂方法)。我还添加了另一个想法,用于根据事实之后的任何谓词来确定排序的描述——我不确定它是否有用,但仍然可以进行有趣的探索!当然,工厂方法会改善这种情况。仍然不理想,但缺乏一种程序化的方法来提取表达式,这可能是最优雅的解决方案。我试图推广该解决方案。请看一个通用实现。
private static Map<Boolean, List<Integer>> testPredicate(Predicate<Integer> predicate) {
    return Stream.of(-35, -3, 2, 5, 17, 29, 30, 460)
            .collect(Collectors.partitioningBy(predicate));
}