泛型也可以应用于接口,例如生成器(Generator),这是一种专门负责创建对象的类。实际上,这是工厂设计模式的一种应用。不过,当使用生成器创建新的对象时,它不需要任何参数,而工厂方法一般需要参数。也就是说,生成器无需额外的信息就知道如何创建新对象。
一般而言,一个生成器只定义一个方法,该方法用以产生新的对象。在这里,就是next()方法。
1 package generics.coffee; 2 3 public interface Generator<T> { 4 T next(); 5 }
方法next()的返回类型是参数化的T。正如你所见到的,接口使用泛型与类使用泛型没有什么区别。
为了演示如何实现Generator接口,我们还需要一些类,如下:
1 package generics.coffee; 2 3 public class Coffee { 4 private static long counter = 0; 5 private final long id = counter++; 6 public String toString(){ 7 return getClass().getSimpleName()+" " + id; 8 } 9 }
1 package generics.coffee; 2 3 public class Breve extends Coffee{}
1 package generics.coffee; 2 3 public class Cappuccino extends Coffee { 4 5 }
1 package generics.coffee; 2 3 public class Americano extends Coffee{ 4 5 }
1 package generics.coffee; 2 3 public class Latte extends Coffeea { 4 5 }
1 package generics.coffee; 2 3 public class Mocah extends Coffee{ 4 5 }
1 package generics.coffee; 2 3 import java.util.*; 4 5 public class CoffeeGenerator implements 6 Generator<Coffee>,Iterable<Coffee>{ 7 private Class[] types = {Latte.class,Mocah.class,Cappuccino.class, 8 Americano.class,Breve.class,}; 9 private static Random rand = new Random(47); 10 public CoffeeGenerator(){} 11 private int size = 0; 12 public CoffeeGenerator(int sz){ 13 size = sz; 14 } 15 16 public Iterator<Coffee> iterator() { 17 // TODO Auto-generated method stub 18 return new CoffeeIterator(); 19 } 20 public Coffee next() { 21 // TODO Auto-generated method stub 22 try{ 23 return (Coffee) 24 types[rand.nextInt(types.length)].newInstance(); 25 }catch(Exception e){ 26 throw new RuntimeException(e); 27 } 28 29 } 30 class CoffeeIterator implements Iterator<Coffee>{ 31 int count = size; 32 public boolean hasNext(){return count>0;} 33 public Coffee next(){ 34 count--; 35 return CoffeeGenerator.this.next(); 36 } 37 public void remove(){ 38 throw new UnsupportedOperationException(); 39 } 40 } 41 42 public static void main(String[] args){ 43 CoffeeGenerator gen = new CoffeeGenerator(); 44 for(int i =0;i<5;i++){ 45 System.out.println(gen.next()); 46 47 } 48 for(Coffee c:new CoffeeGenerator(5)){ 49 System.out.println(c); 50 } 51 } 52 53 }
结果如下:
1 Americano 0 2 Latte 1 3 Americano 2 4 Mocah 3 5 Mocah 4 6 Breve 5 7 Americano 6 8 Latte 7 9 Cappuccino 8 10 Cappuccino 9
参数化的Generator接口确保next()的返回值是参数类型。CoffeeGenerator同时还实现了Iterable接口,所以它可以再循环语句中使用。不过,他还需要一个末端哨兵
来判断何时停止,这正是第二个构造器的功能。