如果您使用Scala或Ceylon甚至JavaScript等更高级的语言进行编程,则“嵌套函数”或“本地函数”是您非常常见的习惯用法。 例如,您将编写诸如fibonacci函数之类的东西:
def f() = {
def g() = "a string!"
g() + "– says g"
}
f()函数包含一个嵌套的g()函数,该函数对于外部f()函数的作用域是局部的。
在Java中,无法创建这样的局部函数,但是您可以将lambda表达式分配给局部变量,然后使用它。
上面的示例可以转换为以下Java代码:
String f() {
Supplier<String> g = () -> "a string!";
return g.get() + "- says g";
}
尽管这个例子很简单,但测试一个更有用的用例。 例如,请考虑以下jOOλ单元测试 ,它检查是否Stream.close()的语义正确跨越各种jOOλ实施Seq方法,即两股合并为一个:
@Test
public void testCloseCombineTwoSeqs() {
Consumer<BiFunction<Stream<Integer>, Stream<Integer>, Seq<?>>> test = f -> {
AtomicBoolean closed1 = new AtomicBoolean();
AtomicBoolean closed2 = new AtomicBoolean();
Stream s1 = Stream.of(1, 2).onClose(() -> closed1.set(true));
Stream s2 = Stream.of(3).onClose(() -> closed2.set(true));
try (Seq s3 = f.apply(s1, s2)) {
s3.collect(Collectors.toList());
}
assertTrue(closed1.get());
assertTrue(closed2.get());
};
test.accept((s1, s2) -> seq(s1).concat(s2));
test.accept((s1, s2) -> seq(s1).crossJoin(s2));
test.accept((s1, s2) -> seq(s1).innerJoin(s2, (a, b) -> true));
test.accept((s1, s2) -> seq(s1).leftOuterJoin(s2, (a, b) -> true));
test.accept((s1, s2) -> seq(s1).rightOuterJoin(s2, (a, b) -> true));
}
局部函数是test ,它接受两个Stream<Integer>参数,产生一个Seq<?>结果。
为什么不只写私有方法呢?
当然,这也可以通过私有方法(经典的Java风格)解决。 但是有时候,使用局部作用域会更加方便,因为测试Consumer (局部功能)无法逃脱该单个单元测试的作用域。 仅应在此单一方法内使用。
另一种更经典的Java方法是定义一个本地类,然后将函数放入其中。 但是这种解决方案更加精益。
但是,一个缺点是,在Java中,以这种方式实现递归要困难得多。
翻译自: https://www.javacodegeeks.com/2016/02/abusing-java-8-functionalinterfaces-local-methods.html
Java 8中利用函数接口与局部方法
本文探讨了如何在Java 8中使用函数接口和局部方法来创建更简洁、灵活的代码。通过实例展示了如何在测试场景中利用这些特性,以及它们与传统私有方法和本地类的对比。文章还讨论了这种方法在递归实现上的局限性。
169万+

被折叠的 条评论
为什么被折叠?



