@@ -359,11 +359,215 @@ brown over fox quick quick dog brown The brown lazy brown
359359` RandomList ` 继承了 ` ArrayList ` 的所有方法。本例中只添加了 ` select() ` 这个方法。
360360
361361<!-- Generic Interfaces -->
362-
363362## 泛型接口
364363
364+ 泛型也可以应用于接口。例如 * 生成器* ,这是一种专门负责创建对象的类。实际上,这是 * 工厂方法* 设计模式的一种应用。不过,当使用生成器创建新的对象时,它不需要任何参数,而工厂方法一般需要参数。生成器无需额外的信息就知道如何创建新对象。
365+
366+ 一般而言,一个生成器只定义一个方法,用于创建对象。例如 ` java.util.function ` 类库中的 ` Supplier ` 就是一个生成器,调用其 ` get() ` 获取对象。` get() ` 是泛型方法,返回值为类型参数 ` T ` 。
367+
368+ 为了演示 ` Supplier ` ,我们需要定义几个类。下面是个咖啡相关的继承体系:
369+
370+ ``` java
371+ // generics/coffee/Coffee.java
372+ package generics.coffee ;
373+
374+ public class Coffee {
375+ private static long counter = 0 ;
376+ private final long id = counter++ ;
377+
378+ @Override
379+ public String toString () {
380+ return getClass(). getSimpleName() + " " + id;
381+ }
382+ }
383+
384+
385+ // generics/coffee/Latte.java
386+ package generics.coffee ;
387+ public class Latte extends Coffee {}
388+
389+
390+ // generics/coffee/Mocha.java
391+ package generics.coffee ;
392+ public class Mocha extends Coffee {}
393+
394+
395+ // generics/coffee/Cappuccino.java
396+ package generics.coffee ;
397+ public class Cappuccino extends Coffee {}
398+
399+
400+ // generics/coffee/Americano.java
401+ package generics.coffee ;
402+ public class Americano extends Coffee {}
403+
404+
405+ // generics/coffee/Breve.java
406+ package generics.coffee ;
407+ public class Breve extends Coffee {}
408+ ```
409+
410+ 现在,我们可以编写一个类,实现 ` Supplier<Coffee> ` 接口,它能够随机生成不同类型的 ` Coffee ` 对象:
411+
412+ ``` java
413+ // generics/coffee/CoffeeSupplier.java
414+ // {java generics.coffee.CoffeeSupplier}
415+ package generics.coffee ;
416+ import java.util.* ;
417+ import java.util.function.* ;
418+ import java.util.stream.* ;
419+
420+ public class CoffeeSupplier
421+ implements Supplier<Coffee > , Iterable<Coffee > {
422+ private Class<?> [] types = { Latte . class, Mocha . class,
423+ Cappuccino . class, Americano . class, Breve . class };
424+ private static Random rand = new Random (47 );
425+
426+ public CoffeeSupplier () {}
427+ // For iteration:
428+ private int size = 0 ;
429+ public CoffeeSupplier (int sz ) { size = sz; }
430+
431+ @Override
432+ public Coffee get () {
433+ try {
434+ return (Coffee ) types[rand. nextInt(types. length)]. newInstance();
435+ } catch (InstantiationException | IllegalAccessException e) {
436+ throw new RuntimeException (e);
437+ }
438+ }
439+
440+ class CoffeeIterator implements Iterator<Coffee > {
441+ int count = size;
442+ @Override
443+ public boolean hasNext () { return count > 0 ; }
444+ @Override
445+ public Coffee next () {
446+ count-- ;
447+ return CoffeeSupplier . this . get();
448+ }
449+ @Override
450+ public void remove () {
451+ throw new UnsupportedOperationException ();
452+ }
453+ }
454+
455+ @Override
456+ public Iterator<Coffee > iterator () {
457+ return new CoffeeIterator ();
458+ }
459+
460+ public static void main (String [] args ) {
461+ Stream . generate(new CoffeeSupplier ())
462+ .limit(5 )
463+ .forEach(System . out:: println);
464+ for (Coffee c : new CoffeeSupplier (5 )) {
465+ System . out. println(c);
466+ }
467+ }
468+ }
469+ ```
470+
471+ 输出结果:
472+
473+ ``` java
474+ Americano 0
475+ Latte 1
476+ Americano 2
477+ Mocha 3
478+ Mocha 4
479+ Breve 5
480+ Americano 6
481+ Latte 7
482+ Cappuccino 8
483+ Cappuccino 9
484+ ```
485+
486+ 参数化的 ` Supplier ` 接口确保 ` get() ` 返回值是参数的类型。` CoffeeSupplier ` 同时还实现了 ` Iterable ` 接口,所以能用于 * for-in* 语句。不过,它还需要知道何时终止循环,这正是第二个构造函数的作用。
487+
488+ 下面是另一个实现 ` Supplier<T> ` 接口的例子,它负责生成 Fibonacci 数列:
489+
490+ ``` java
491+ // generics/Fibonacci.java
492+ // Generate a Fibonacci sequence
493+ import java.util.function.* ;
494+ import java.util.stream.* ;
495+
496+ public class Fibonacci implements Supplier<Integer > {
497+ private int count = 0 ;
498+ @Override
499+ public Integer get () { return fib(count++ ); }
500+
501+ private int fib (int n ) {
502+ if (n < 2 ) return 1 ;
503+ return fib(n- 2 ) + fib(n- 1 );
504+ }
505+
506+ public static void main (String [] args ) {
507+ Stream . generate(new Fibonacci ())
508+ .limit(18 )
509+ .map(n - > n + " " )
510+ .forEach(System . out:: print);
511+ }
512+ }
513+ ```
514+
515+ 输出结果:
516+
517+ ``` java
518+ 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
519+ ```
520+
521+ 虽然我们在 ` Fibonacci ` 类的里里外外使用的都是 ` int ` 类型,但是其参数类型却是 ` Integer ` 。这个例子引出了 Java 泛型的一个局限性:基本类型无法作为类型参数。不过 Java 5 具备自动装箱和拆箱的功能,可以很方便地在基本类型和相应的包装类之间进行转换。通过这个例子中 ` Fibonacci ` 类对 ` int ` 的使用,我们已经看到了这种效果。
522+
523+ 如果还想更进一步,编写一个实现了 ` Iterator ` 的 ` Fibnoacci ` 生成器。我们的一个选择是重写这个类,令其实现 ` Iterator ` 接口。不过,你并不是总能拥有源代码的控制权,并且,除非必须这么做,否则,我们也不愿意重写一个类。而且我们还有另一种选择,就是创建一个 * 适配器* (Adapter) 来实现所需的接口,我们在前面介绍过这个设计模式。
524+
525+ 有多种方法可以实现适配器。例如,可以通过继承来创建适配器类:
526+
527+ ``` java
528+ // generics/IterableFibonacci.java
529+ // Adapt the Fibonacci class to make it Iterable
530+ import java.util.* ;
531+
532+ public class IterableFibonacci
533+ extends Fibonacci implements Iterable<Integer > {
534+ private int n;
535+ public IterableFibonacci (int count ) { n = count; }
536+
537+ @Override
538+ public Iterator<Integer > iterator () {
539+ return new Iterator<Integer > () {
540+ @Override
541+ public boolean hasNext () { return n > 0 ; }
542+ @Override
543+ public Integer next () {
544+ n-- ;
545+ return IterableFibonacci . this . get();
546+ }
547+ @Override
548+ public void remove () { // Not implemented
549+ throw new UnsupportedOperationException ();
550+ }
551+ };
552+ }
553+
554+ public static void main (String [] args ) {
555+ for (int i : new IterableFibonacci (18 ))
556+ System . out. print(i + " " );
557+ }
558+ }
559+ ```
560+
561+ 输出结果:
562+
563+ ``` java
564+ 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
565+ ```
566+
567+ 在循环语句中使用 ` IterableFibonacci ` ,必须在构造函数中提供一个边界值,这样 ` hasNext() ` 才知道何时返回 ** false** ,结束循环。
365568
366569<!-- Generic Methods -->
570+
367571## 泛型方法
368572
369573
0 commit comments