Skip to content

Commit b2b557e

Browse files
committed
Closure
1 parent 843b0f9 commit b2b557e

File tree

1 file changed

+10
-11
lines changed

1 file changed

+10
-11
lines changed

docs/book/13-Functional-Programming.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ public class TriFunctionTest {
870870
}
871871
```
872872

873-
这里我们测试方法引用和 Lambda 表达式。
873+
这里我们测试了方法引用和 Lambda 表达式。
874874

875875
### 缺少基本类型的函数
876876

@@ -904,7 +904,7 @@ public class BiConsumerPermutations {
904904
1, 11
905905
```
906906

907-
这里使用 `System.out.format()` 来显示。它类似于 `System.out.println()` 但提供了更多的显示选项。 这里,`%f` 表示我将 `n` 作为浮点值给出,`%d` 表示 `n` 是一个整数值。 我能够包含空格,并且它不会添加换行符,除非你输入 `%n` - 它也会接受传统 `\n` 换行符,但 `%n` 是自动跨平台的,这是使用的 `format()` 的另一个原因。
907+
这里使用 `System.out.format()` 来显示。它类似于 `System.out.println()` 但提供了更多的显示选项。 这里,`%f` 表示我将 `n` 作为浮点值给出,`%d` 表示 `n` 是一个整数值。 这其中可以包含空格,输入 `%n` 会换行 — 当然使用传统的 `\n` 也能换行,但 `%n` 是自动跨平台的,这是使用 `format()` 的另一个原因。
908908

909909
上例简单使用了包装类型,装箱和拆箱用于在基本类型之间来回转换。 我们也可以使用包装类型,如 `Function`,而不是预定义的基本类型。代码示例:
910910

@@ -940,7 +940,7 @@ public interface IntToDoubleFunction {
940940
## 高阶函数
941941

942942

943-
这个名字听起来有点令人生畏,但是:[高阶函数](https://en.wikipedia.org/wiki/Higher-order_function)(Higher-order Function)只是一个消费或产生函数的函数。
943+
这个名字可能听起来令人生畏,但是:[高阶函数](https://en.wikipedia.org/wiki/Higher-order_function)(Higher-order Function)只是一个消费或产生函数的函数。
944944

945945
我们先来看看如何产生一个函数:
946946

@@ -970,9 +970,9 @@ yelling
970970

971971
这里,`produce()` 是高阶函数。
972972

973-
**[1]** 使用继承,可以轻松地为你的专用接口创建别名
973+
**[1]** 使用继承,可以轻松地为专用接口创建别名
974974

975-
**[2]** 使用 Lambda 表达式,在方法中轻松创建和返回一个函数
975+
**[2]** 使用 Lambda 表达式,可以轻松地在方法中创建和返回一个函数
976976

977977
要消费一个函数,消费函数需要在参数列表正确地描述函数类型。代码示例:
978978

@@ -994,7 +994,7 @@ public class ConsumeFunction {
994994
}
995995
```
996996

997-
有趣的是,根据消费函数生成新函数。代码示例
997+
当基于消费函数生成新函数时,事情就变得相当有趣了。代码示例如下
998998

999999
```java
10001000
// functional/TransformFunction.java
@@ -1037,19 +1037,18 @@ O
10371037

10381038
在这里,`transform()` 生成一个与传入的函数具有相同签名的函数,但是你可以生成任何你想要的类型。
10391039

1040-
这在 `Function` 接口中使用名为 `andThen()` 的默认方法,该方法专门用于操作函数。 顾名思义,在调用 `in` 函数之后调用 `toThen()`还有 `compose()`,它在 `in` 函数之前应用新函数)。 要附加一个 `andThen()` 函数,我们只需将该函数作为参数传递。 `transform()` 产生的是一个新函数,它将 `in` 的动作与 `andThen()` 参数的动作结合起来。
1040+
这里使用到了 `Function` 接口中名为 `andThen()` 的默认方法,该方法专门用于操作函数。 顾名思义,在调用 `in` 函数之后调用 `toThen()`还有个 `compose()` 方法,它在 `in` 函数之前应用新函数)。 要附加一个 `andThen()` 函数,我们只需将该函数作为参数传递。 `transform()` 产生的是一个新函数,它将 `in` 的动作与 `andThen()` 参数的动作结合起来。
10411041

10421042
<!-- Closures -->
1043+
10431044
## 闭包
10441045

10451046

10461047
在上一节的 `ProduceFunction.java` 中,我们从方法中返回 Lambda 函数。 虽然过程简单,但是有些问题必须再回过头来探讨一下。
10471048

10481049
**闭包**(Closure)一词总结了这些问题。 它非常重要,利用闭包可以轻松生成函数。
10491050

1050-
考虑一个更复杂的 Lambda,它使用函数作用域之外的变量。 返回该函数会发生什么? 也就是说,当你调用函数时,它对那些 “外部 ”变量引用了什么? 如果语言不能自动解决这个问题,那将变得非常具有挑战性。 能够解决这个问题的语言被称为**支持闭包**,或者在词法上限定范围( 也使用术语变量捕获 )。Java 8 提供了有限但合理的闭包支持,
1051-
1052-
我们将用一些简单的例子来研究它。
1051+
考虑一个更复杂的 Lambda,它使用函数作用域之外的变量。 返回该函数会发生什么? 也就是说,当你调用函数时,它对那些 “外部 ”变量引用了什么? 如果语言不能自动解决这个问题,那将变得非常具有挑战性。 能够解决这个问题的语言被称为**支持闭包**,或者叫作在词法上限定范围( 也使用术语变量捕获 )。Java 8 提供了有限但合理的闭包支持,我们将用一些简单的例子来研究它。
10531052

10541053
首先,下例函数中,方法返回访问对象字段和方法参数。代码示例:
10551054

@@ -1066,7 +1065,7 @@ public class Closure1 {
10661065
}
10671066
```
10681067

1069-
但是,仔细考虑一下,`i` 的这种用法并非是个大难题,因为对象很可能在你调用 `makeFun()` 之后就存在了——实际上,垃圾收集器几乎肯定会保留一个对象,并将现有的函数以这种方式绑定到该对象上[^5]。当然,如果你对同一个对象多次调用 `makeFun()` ,你最终会得到多个函数,它们都为 `i` 共享相同的存储空间:
1068+
但是,仔细考虑一下,`i` 的这种用法并非是个大难题,因为对象很可能在你调用 `makeFun()` 之后就存在了——实际上,垃圾收集器几乎肯定会保留一个对象,并将现有的函数以这种方式绑定到该对象上[^5]。当然,如果你对同一个对象多次调用 `makeFun()` ,你最终会得到多个函数,它们共享 `i` 的存储空间:
10701069
```java
10711070
// functional/SharedStorage.java
10721071

0 commit comments

Comments
 (0)