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

时间:2014-05-16 20:51:32

标签: java lambda tostring java-8 predicates

出于调试目的,我试图在Java 8中创建lambda表达式的字符串表示(特别是Predicate s,尽管它对其他lambda表达式也很有意义)。我的想法是这样的:< / p>

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));
    }

}

输出为i -> i % 2 == 0(或逻辑等效的东西)。 toString()方法似乎无济于事,输出类似于com.something.Whatever$$Lambda$1/1919892312@5e91993f(我猜这是预期的,因为toString()未被覆盖)。

我不确定这样的事情是否可能,例如有了反思,到目前为止,我当然无法找到任何东西。有什么想法吗?

1 个答案:

答案 0 :(得分:16)

我能想到的最简单的事情是创建一个“命名谓词”,为谓词提供名称或描述,基本上任何对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
    }
}

可以说,给出你的谓词名称或这样的描述会使你使用它们的代码更容易理解:

Stream.of(1, 2, 3, 4)
        .filter(isEven)
        .forEach(System.out::println);

一个陌生人的想法可能是导出谓词的“结构”描述,即某些给定输入的输出是什么?显然,当输入集有限且很小时(例如对于枚举,布尔值或其他一些限制集),这将最有效,但我想你也可以为整数谓词尝试一小组“随机”整数:

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));
}

对于isEven,这会返回类似{false=[-35, -3, 5, 17, 29], true=[2, 30, 460]}的内容,我认为这不一定比手动给它们描述更清晰,但对于不在你的下面的谓词可能有用控制。