mirror of
https://github.com/LingCoder/OnJava8.git
synced 2026-08-24 15:03:29 +08:00
Closure
This commit is contained in:
@@ -870,7 +870,7 @@ public class TriFunctionTest {
|
||||
}
|
||||
```
|
||||
|
||||
这里我们测试方法引用和 Lambda 表达式。
|
||||
这里我们测试了方法引用和 Lambda 表达式。
|
||||
|
||||
### 缺少基本类型的函数
|
||||
|
||||
@@ -904,7 +904,7 @@ public class BiConsumerPermutations {
|
||||
1, 11
|
||||
```
|
||||
|
||||
这里使用 `System.out.format()` 来显示。它类似于 `System.out.println()` 但提供了更多的显示选项。 这里,`%f` 表示我将 `n` 作为浮点值给出,`%d` 表示 `n` 是一个整数值。 我能够包含空格,并且它不会添加换行符,除非你输入 `%n` - 它也会接受传统 `\n` 换行符,但 `%n` 是自动跨平台的,这是使用的 `format()` 的另一个原因。
|
||||
这里使用 `System.out.format()` 来显示。它类似于 `System.out.println()` 但提供了更多的显示选项。 这里,`%f` 表示我将 `n` 作为浮点值给出,`%d` 表示 `n` 是一个整数值。 这其中可以包含空格,输入 `%n` 会换行 — 当然使用传统的 `\n` 也能换行,但 `%n` 是自动跨平台的,这是使用 `format()` 的另一个原因。
|
||||
|
||||
上例简单使用了包装类型,装箱和拆箱用于在基本类型之间来回转换。 我们也可以使用包装类型,如 `Function`,而不是预定义的基本类型。代码示例:
|
||||
|
||||
@@ -940,7 +940,7 @@ public interface IntToDoubleFunction {
|
||||
## 高阶函数
|
||||
|
||||
|
||||
这个名字听起来有点令人生畏,但是:[高阶函数](https://en.wikipedia.org/wiki/Higher-order_function)(Higher-order Function)只是一个消费或产生函数的函数。
|
||||
这个名字可能听起来令人生畏,但是:[高阶函数](https://en.wikipedia.org/wiki/Higher-order_function)(Higher-order Function)只是一个消费或产生函数的函数。
|
||||
|
||||
我们先来看看如何产生一个函数:
|
||||
|
||||
@@ -970,9 +970,9 @@ yelling
|
||||
|
||||
这里,`produce()` 是高阶函数。
|
||||
|
||||
**[1]** 使用继承,可以轻松地为你的专用接口创建别名。
|
||||
**[1]** 使用继承,可以轻松地为专用接口创建别名。
|
||||
|
||||
**[2]** 使用 Lambda 表达式,在方法中轻松创建和返回一个函数。
|
||||
**[2]** 使用 Lambda 表达式,可以轻松地在方法中创建和返回一个函数。
|
||||
|
||||
要消费一个函数,消费函数需要在参数列表正确地描述函数类型。代码示例:
|
||||
|
||||
@@ -994,7 +994,7 @@ public class ConsumeFunction {
|
||||
}
|
||||
```
|
||||
|
||||
有趣的是,根据消费函数生成新函数。代码示例:
|
||||
当基于消费函数生成新函数时,事情就变得相当有趣了。代码示例如下:
|
||||
|
||||
```java
|
||||
// functional/TransformFunction.java
|
||||
@@ -1037,9 +1037,10 @@ O
|
||||
|
||||
在这里,`transform()` 生成一个与传入的函数具有相同签名的函数,但是你可以生成任何你想要的类型。
|
||||
|
||||
这在 `Function` 接口中使用名为 `andThen()` 的默认方法,该方法专门用于操作函数。 顾名思义,在调用 `in` 函数之后调用 `toThen()`(还有 `compose()`,它在 `in` 函数之前应用新函数)。 要附加一个 `andThen()` 函数,我们只需将该函数作为参数传递。 `transform()` 产生的是一个新函数,它将 `in` 的动作与 `andThen()` 参数的动作结合起来。
|
||||
这里使用到了 `Function` 接口中名为 `andThen()` 的默认方法,该方法专门用于操作函数。 顾名思义,在调用 `in` 函数之后调用 `toThen()`(还有个 `compose()` 方法,它在 `in` 函数之前应用新函数)。 要附加一个 `andThen()` 函数,我们只需将该函数作为参数传递。 `transform()` 产生的是一个新函数,它将 `in` 的动作与 `andThen()` 参数的动作结合起来。
|
||||
|
||||
<!-- Closures -->
|
||||
|
||||
## 闭包
|
||||
|
||||
|
||||
@@ -1047,9 +1048,7 @@ O
|
||||
|
||||
**闭包**(Closure)一词总结了这些问题。 它非常重要,利用闭包可以轻松生成函数。
|
||||
|
||||
考虑一个更复杂的 Lambda,它使用函数作用域之外的变量。 返回该函数会发生什么? 也就是说,当你调用函数时,它对那些 “外部 ”变量引用了什么? 如果语言不能自动解决这个问题,那将变得非常具有挑战性。 能够解决这个问题的语言被称为**支持闭包**,或者在词法上限定范围( 也使用术语变量捕获 )。Java 8 提供了有限但合理的闭包支持,
|
||||
|
||||
我们将用一些简单的例子来研究它。
|
||||
考虑一个更复杂的 Lambda,它使用函数作用域之外的变量。 返回该函数会发生什么? 也就是说,当你调用函数时,它对那些 “外部 ”变量引用了什么? 如果语言不能自动解决这个问题,那将变得非常具有挑战性。 能够解决这个问题的语言被称为**支持闭包**,或者叫作在词法上限定范围( 也使用术语变量捕获 )。Java 8 提供了有限但合理的闭包支持,我们将用一些简单的例子来研究它。
|
||||
|
||||
首先,下例函数中,方法返回访问对象字段和方法参数。代码示例:
|
||||
|
||||
@@ -1066,7 +1065,7 @@ public class Closure1 {
|
||||
}
|
||||
```
|
||||
|
||||
但是,仔细考虑一下,`i` 的这种用法并非是个大难题,因为对象很可能在你调用 `makeFun()` 之后就存在了——实际上,垃圾收集器几乎肯定会保留一个对象,并将现有的函数以这种方式绑定到该对象上[^5]。当然,如果你对同一个对象多次调用 `makeFun()` ,你最终会得到多个函数,它们都为 `i` 共享相同的存储空间:
|
||||
但是,仔细考虑一下,`i` 的这种用法并非是个大难题,因为对象很可能在你调用 `makeFun()` 之后就存在了——实际上,垃圾收集器几乎肯定会保留一个对象,并将现有的函数以这种方式绑定到该对象上[^5]。当然,如果你对同一个对象多次调用 `makeFun()` ,你最终会得到多个函数,它们共享 `i` 的存储空间:
|
||||
```java
|
||||
// functional/SharedStorage.java
|
||||
|
||||
|
||||
Reference in New Issue
Block a user