Skip to content

Commit db96464

Browse files
committed
add
Signed-off-by: maskleo <[email protected]>
1 parent 742e25c commit db96464

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

ch09/03_Function.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
## 功能
2+
3+
函数模式将任意方法转换为对象。函数和相应方法之间的关系类似于 `Comparator``compareTo` 方法之间的关系。
4+
5+
函数模式的通用版本演示了如何在方法声明的 `throws` 子句中使用类型变量。当一个类的不同实例包含可能引发不同检查异常的方法时,这可能很有用。
6+
7+
回想一下 `Throwable` 类有两个主要的子类 `Exception``Error`,其中第一个子类有另一个主要的子类 `RuntimeException`。检查异常是否是 `RuntimeException``Error` 的子类。方法的 `throws` 子句可以列出 `Throwable` 的任何子类,但必须列出方法体可能抛出的任何检查异常,包括为正文中调用的方法声明的任何检查异常。
8+
9+
`9-5` 给出了一个在 `throws` 子句中使用类型变量的例子。该示例定义了一个接口 `Function<A,B,X>`,它表示一个函数。接口包含一个方法 `apply`,它接受 `A` 类型的参数,返回类型 `B` 的结果,并且可以抛出类型的异常 `X` 。还有一个包含 `applyAll`方法的类。
10+
11+
`9-5`。在 `throws` 子句中输入参数
12+
13+
```java
14+
import java.util.*;
15+
import java.lang.reflect.*;
16+
interface Function<A, B, X extends Throwable> {
17+
public B apply(A x) throws X;
18+
}
19+
class Functions {
20+
public static <A, B, X extends Throwable> List<B> applyAll(Function<A, B, X> f, List<A> list) throws X {
21+
List<B> result = new ArrayList<B>(list.size());
22+
for (A x : list)
23+
result.add(f.apply(x));
24+
return result;
25+
}
26+
public static void main(String[] args) {
27+
Function<String, Integer, Error> length = new Function<String, Integer, Error>() {
28+
public Integer apply(String s) {
29+
return s.length();
30+
}
31+
};
32+
Function<String, Class<?>, ClassNotFoundException> forName = new Function<String, Class<?>, ClassNotFoundException>() {
33+
public Class<?> apply(String s) throws ClassNotFoundException {
34+
return Class.forName(s);
35+
}
36+
};
37+
Function<String, Method, Exception> getRunMethod = new Function<String, Method, Exception>() {
38+
public Method apply(String s) throws ClassNotFoundException,NoSuchMethodException {
39+
return Class.forName(s).getMethod("run");
40+
}
41+
};
42+
List<String> strings = Arrays.asList(args);
43+
System.out.println(applyAll(length, strings));
44+
try {
45+
System.out.println(applyAll(forName, strings));
46+
} catch (ClassNotFoundException e) {
47+
System.out.println(e);
48+
}
49+
try {
50+
System.out.println(applyAll(getRunMethod, strings));
51+
} catch (ClassNotFoundException e) {
52+
System.out.println(e);
53+
} catch (NoSuchMethodException e) {
54+
System.out.println(e);
55+
} catch (RuntimeException e) {
56+
throw e;
57+
} catch (Exception e) {
58+
throw new AssertionError();
59+
}
60+
}
61+
}
62+
```
63+
64+
它接受 `List<A>` 类型的参数,返回 `List<B>` 类型的结果,并且可能再次引发 `X` 类型的异常; 该方法在参数列表的每个元素上调用 `apply` 方法来生成结果列表。
65+
66+
该类的主要方法定义了这种类型的三个对象。 第一个是 `Function<String,Integer,Error>` 类型的长度。 它接受一个字符串并返回一个整数,它是给定字符串的长度。 由于它没有引发检查异常,因此第三种类型设置为错误。(将其设置为 `RuntimeException` 也可以。)
67+
68+
第二个是 `forName` 类型的 `Function<String,Class <?>,ClassNotFoundException>`。 它接受一个字符串并返回一个类,即由给定字符串命名的类。 `apply` 方法可能会抛出一个 `ClassNotFoundException`,所以这被当作第三个类型参数。
69+
70+
第三个是 `Function<String,Method,Exception>` 类型的 `getRunMethod`。它接受一个字符串并返回一个方法,即在给定字符串所指定的类中名为 `run` 的方法。该方法的主体可能会引发 `ClassNotFoundException``NoSuchMethodException`,因此第三个类型参数将被视为 `Exception`,这是包含这两个异常的最小类。
71+
72+
最后一个例子显示了将泛型类型用于异常的主要限制。通常没有合适的类或接口包含函数可能引发的所有异常,因此您不得不重新使用异常,这太笼统,无法提供有用的信息。
73+
74+
主要方法使用 `applyAll` 将三个函数中的每一个应用于字符串列表。三个调用中的每一个都被包装在一个 `try` 语句中,该语句适合于它可能抛出的异常。长度函数没有 `try` 语句,因为它不引发检查异常。 `forName` 函数有一个带有 `ClassNotFoundException``catch` 子句的 `try` 语句,它可能抛出一种异常。`getRunMethod` 函数需要一个带有 `catch` 子句的 `try` 语句,用于 `ClassNotFoundException``NoSuchMethodException`,它可能抛出两种异常。但是该函数被声明为抛出 `Exception` 类型,所以我们需要两个额外的“catchall”子句,一个重新抛出引发的任何运行时异常,另一个断言如果发生任何未处理的异常由前三条规定。对于这个特定的例子,不需要重新提升运行时异常,但是如果可能有其他代码处理这些异常,这是一个好习惯。
75+
76+
例如,下面是典型的代码运行,打印长度列表,类别列表和方法列表(最后一个列表为了便于阅读而重新格式化,因为它不适合一行):
77+
78+
```java
79+
% java Functions java.lang.Thread java.lang.Runnable
80+
[16, 18]
81+
[class java.lang.Thread, interface java.lang.Runnable]
82+
[public void java.lang.Thread.run(),
83+
public abstract void java.lang.Runnable.run()]
84+
```
85+
86+
这是一个引发 `NoSuchMethodException` 的运行,因为 `java.util.List` 没有 `run` 方法:
87+
88+
```java
89+
% java Functions java.lang.Thread java.util.List
90+
[16, 14]
91+
[class java.lang.Thread, interface java.util.List]
92+
java.lang.NoSuchMethodException: java.util.List.run()
93+
```
94+
95+
这是一个引发 `ClassNotFoundException` 的运行,因为没有名为 `Fred` 的类:
96+
97+
```java
98+
% java Functions java.lang.Thread Fred
99+
[16, 4]
100+
java.lang.ClassNotFoundException: Fred
101+
java.lang.ClassNotFoundException: Fred
102+
```
103+
104+
该异常会引发两次,一次是在应用 `forName` 时,一次是在应用 `getRunMethod` 时引发的。
105+
106+
107+
108+
109+
110+
111+
112+
113+
114+
115+
116+
117+
118+
119+
120+
121+
122+
123+
124+
125+
126+
127+
128+
129+
130+
131+
132+
133+
134+
135+

0 commit comments

Comments
 (0)