@@ -259,6 +259,105 @@ public class TupleTest {
259
259
260
260
在上面的程序中,` new ` 表达式有些啰嗦。本章稍后会介绍,如何利用 * 泛型方法* 简化它们。
261
261
262
+ ### 一个堆栈类
263
+
264
+ 接下来我们看一个稍微复杂一点的例子:堆栈。在[ 集合] ( ./12-Collections.md ) 一章中,我们用 ` LinkedList ` 实现了 ` onjava.Stack ` 类。在那个例子中,` LinkedList ` 本身已经具备了创建堆栈所需的方法。` Stack ` 是通过两个泛型类 ` Stack<T> ` 和 ` LinkedList<T> ` 的组合来创建。我们可以看出,泛型只不过是一种类型罢了(稍后我们会看到一些例外的情况)。
265
+
266
+ 这次我们不用 ` LinkedList ` 来实现自己的内部链式存储机制。
267
+
268
+ ``` java
269
+ // generics/LinkedStack.java
270
+ // 用链式结构实现的堆栈
271
+
272
+ public class LinkedStack <T> {
273
+ private static class Node <U> {
274
+ U item;
275
+ Node<U > next;
276
+
277
+ Node () { item = null ; next = null ; }
278
+ Node (U item , Node<U > next ) {
279
+ this . item = item;
280
+ this . next = next;
281
+ }
282
+
283
+ boolean end () {
284
+ return item == null && next == null ;
285
+ }
286
+ }
287
+
288
+ private Node<T > top = new Node<> (); // 栈顶
289
+
290
+ public void push (T item ) {
291
+ top = new Node<> (item, top);
292
+ }
293
+
294
+ public T pop () {
295
+ T result = top. item;
296
+ if (! top. end()) {
297
+ top = top. next;
298
+ }
299
+ return result;
300
+ }
301
+
302
+ public static void main (String [] args ) {
303
+ LinkedStack<String > lss = new LinkedStack<> ();
304
+ for (String s : " Phasers on stun!" . split(" " )) {
305
+ lss. push(s);
306
+ }
307
+ String s;
308
+ while ((s = lss. pop()) != null ) {
309
+ System . out. println(s);
310
+ }
311
+ }
312
+ }
313
+ ```
314
+
315
+ 输出结果:
316
+
317
+ ``` java
318
+ stun!
319
+ on
320
+ Phasers
321
+ ```
322
+
323
+ 内部类 ` Node ` 也是一个泛型,它拥有自己的类型参数。
324
+
325
+ 这个例子使用了一个 * 末端标识* (end sentinel) 来判断栈何时为空。这个末端标识是在构造 ` LinkedStack ` 时创建的。然后,每次调用 ` push() ` 就会创建一个 ` Node<T> ` 对象,并将其链接到前一个 ` Node<T> ` 对象。当你调用 ` pop() ` 方法时,总是返回 ` top.item ` ,然后丢弃当前 ` top ` 所指向的 ` Node<T> ` ,并将 ` top ` 指向下一个 ` Node<T> ` ,除非到达末端标识,这时就不能再移动 ` top ` 了。如果已经到达末端,程序还继续调用 ` pop() ` 方法,它只能得到 ` null ` ,说明栈已经空了。
326
+
327
+ ### RandomList
328
+
329
+ 作为容器的另一个例子,假设我们需要一个持有特定类型对象的列表,每次调用它的 ` select() ` 方法时都随机返回一个元素。如果希望这种列表可以适用于各种类型,就需要使用泛型:
330
+
331
+ ``` java
332
+ // generics/RandomList.java
333
+ import java.util.* ;
334
+ import java.util.stream.* ;
335
+
336
+ public class RandomList <T> extends ArrayList<T > {
337
+ private Random rand = new Random (47 );
338
+
339
+ public T select () {
340
+ return get(rand. nextInt(size()));
341
+ }
342
+
343
+ public static void main (String [] args ) {
344
+ RandomList<String > rs = new RandomList<> ();
345
+ Array . stream(" The quick brown fox jumped over the lazy brown dog" . split(" " )). forEach(rs:: add);
346
+ IntStream . range(0 , 11 ). forEach(i - >
347
+ System . out. print(rs. select() + " " ));
348
+ );
349
+ }
350
+ }
351
+ ```
352
+
353
+ 输出结果:
354
+
355
+ ``` java
356
+ brown over fox quick quick dog brown The brown lazy brown
357
+ ```
358
+
359
+ ` RandomList ` 继承了 ` ArrayList ` 的所有方法。本例中只添加了 ` select() ` 这个方法。
360
+
262
361
<!-- Generic Interfaces -->
263
362
264
363
## 泛型接口
0 commit comments