【问题标题】:Creating String representation of lambda expression [duplicate]创建 lambda 表达式的字符串表示
【发布时间】:2014-05-16 20:51:31
【问题描述】:

出于调试目的,我尝试在 Java 8 中创建 lambda 表达式(特别是 Predicates,尽管它对其他 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));
    }

}

输出将是i -&gt; i % 2 == 0(或逻辑上等价的东西)。 toString() 方法似乎没有任何帮助,输出类似于 com.something.Whatever$$Lambda$1/1919892312@5e91993f (我猜这是可以预料的,因为 toString() 没有被覆盖)。

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

【问题讨论】:

  • 调试目的?不能只看源码吗?
  • 这需要反编译器。
  • @SotiriosDelimanolis 当然,我总是可以查看源代码。但最好有一个可打印的表示。
  • 那不能直接复制源码吗?
  • @JeroenVannevel 你的意思是每次都手动编写一个字符串表示?可能,当然。但不是很优雅。

标签: java lambda tostring java-8 predicates


【解决方案1】:

我能想到的最简单的事情是创建一个“命名谓词”,它为您的谓词提供名称或描述,基本上任何可以用作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]} 的内容,我认为这不一定比您手动给它们描述更清楚,但对于不受您控制的谓词可能有用。

【讨论】:

  • 虽然这应该可以工作,但 lambda 表达式语法的美妙之处在这里部分丢失了,因为包装对象 NamedPredicate 必须使用 new 运算符创建。
  • @blalasaadri 是的。我想你可以通过创建一个静态工厂方法来隐藏一些像 new&lt;&gt; 这样的丑陋(参见例如所有的 Guava 集合工厂方法)。我还添加了另一个想法,用于在事后从任何谓词中确定排序描述 - 我不确定它是否有用,但探索起来可能很有趣!
  • 工厂方法肯定会改善这种情况。仍然不理想,但缺乏提取表达式的编程方式,这可能是最优雅的解决方案。
  • 我试图概括解决方案。查看stackoverflow.com/a/42876841/1325574 的通用实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 2019-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多