泛型接口

泛型也可以应用于接口。例如生成器,这是一种专门负责创建对象的类。实际上,这是工厂方法设计模式的一种应用。不够,当使用生成器创建新的对象的时候,它不需要任何参数,而工厂方法一般需要参数。也就是说,生成器无需额外的信息就知道如何创建新对象。

一般而言,一个生成器制定以一个方法,以该方法用以产生新的对象。在这里,就是next方法。

public interface Generator<T> {
	T next();
}

方法next()的返回函数是参数化的T。正如你所见到的,接口使用泛型与类使用泛型没有什么区别。

为了演示如何实现Generator接口,我们还需要一些别的类,例如,Coffee类的层次结构如下:

public class Coffee {
	private static long counter=0;//计数器,来计算已成生coffee实例的数量
	private final long id=counter++;//id,final类型,当初始化之后,不可变,记录此实例对象的ID
	public String toString(){
		return getClass().getSimpleName()+""+id;
	}
}
public class Mocha extends Coffee{

}
public class Cappuccino extends Coffee{

}
public class Latte extends Coffee{

}

现在我们编写一个类,实现Generator<Coffee>接口,他能够随机生成不同类型的Coffee对象:

public class CoffeeGenerator implements Generator<Coffee>,Iterable<Coffee>{
	private Class[] types={Latte.class,Mocha.class,Cappuccino.class};
	private static Random rand=new Random(47);
	public CoffeeGenerator(){};
	private int size=0;
	public CoffeeGenerator(int size){
		this.size=size;
	}
	@Override
	public Coffee next() {
		// TODO Auto-generated method stub
		try {
			return (Coffee)types[rand.nextInt(types.length)].newInstance();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
	class CoffeeIterator<Coffee> implements Iterator{

		int count=size;
		@Override
		public boolean hasNext() {
			// TODO Auto-generated method stub
			return count>0;
		}
		@Override
		public Object next() {
			// TODO Auto-generated method stub
			count--;
			return CoffeeGenerator.this.next();
		}
		@Override
		public void remove() {
			// TODO Auto-generated method stub
		}	
	}

	@Override
	public Iterator<Coffee> iterator() {
		// TODO Auto-generated method stub
		return new CoffeeIterator();
	}
	public static void main(String[] args) {
		CoffeeGenerator cg=new CoffeeGenerator();
		for(int i=0;i<5;i++){
			System.out.println(cg.next());
		}
		for(Coffee c:new CoffeeGenerator(5)){
			System.out.println(c);
		}
	}	

}

参数化的Generator接口确保next()函数返回值是参数的类型。CoffeeGenerator同时还实现了Iterable接口,所以他可以在循环语句中使用(foreach语法详见http://blog.csdn.net/fxkcsdn/article/details/76576652)。不过,它还需要一个末端哨兵来判断何时停止,这正是第二个构造器的功能。

下面的类是Generator<T>接口的另一个实现,它负责生成Fibonacci数列:

public class Fibonacci implements Generator<Integer>{

	private int count=0;
	@Override
	public Integer next() {
		// TODO Auto-generated method stub
		return fbc(count++);
	}
	public int fbc(int n){
		if(n<2){
			return 1;
		}else{
			return fbc(n-1)+fbc(n-2);
		}
	}
	public static void main(String[] args) {
		Fibonacci fc=new Fibonacci();
		for(int i=0;i<10;i++){
			System.out.println(fc.next());
		}
	}
}

虽然我们在Fibonacci类的里里外外使用的都是int类型,但是其类型参数确实Integer.这个例子引出了Java泛型的一个局限性:基本类型无法作为类型参数。不过,javaSE5具备了自动打包和自动拆包的功能,可以很方便的在基本类型和其对应的包装器类型之间进行转换。通过这个例子中的Fibonacci类对Int的使用,我们已经看到了这种效果。

如果还想更近一步,编写一个实现Iterable的FIbonacci生成器。我们的一个选择是充血这个类,令其实现Iterable接口。不过,你并不是总能拥有源代码的控制权,并且,除非必须这么做,否则,我们也不愿意重写一个类。而且我们还有另一种选择,就是创建一个适配器。来实现所需的接口。

有多种方法实现适配器。例如,可以通过继承来创建适配器:

public class IterableFibonacci extends Fibonacci implements Iterable<Integer>{
	private int size;
	public IterableFibonacci(int size){
		this.size=size;
	}
	@Override
	public Iterator<Integer> iterator() {
		// TODO Auto-generated method stub
		return new Iterator<Integer>(){
			@Override
			public boolean hasNext() {
				// TODO Auto-generated method stub
				return size>0;
			}
			@Override
			public Integer next() {
				// TODO Auto-generated method stub
				size--;
				return IterableFibonacci.this.next();
			}
			@Override
			public void remove() {
				// TODO Auto-generated method stub
				throw new UnsupportedOperationException();
			}			
		};
	}
	public static void main(String[] args) {
		IterableFibonacci ifc=new IterableFibonacci(10);
		for(Integer i:ifc){
			System.out.println(i);
		}
	}
}

如果要在循环语句中使用IterableFibonacci,必须向IterableFinacci的构造器提供一个边界值,然后hasnext()方法才能知道何时返回false.




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值