This commit is contained in:
xiangflight
2019-08-06 14:05:53 +08:00
parent 843b0f9297
commit b2b557eb96

View File

@@ -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