一、问题
Think in Java 中有一个很经典的讲泛型的例子,下面我们就来分析一下:
package com.caliper.body.service;
import com.caliper.body.domain.*;
import net.mindview.util.Generator;
import java.util.Iterator;
import java.util.Random;
/*** @author Auther* @title: CoffeeGenerator* @projectName demo* @description: 咖啡机实体类* @date 09/05/201909:26*/
public class CoffeeGenerator implements Generator,Iterable {
/*** 所有咖啡的类型*/
private Class[] types = {Latte.class, Mocha.class, Cappuccino.class, Americano.class,Breve.class} ;
/*** 随机数*/
private static Random random = new Random();
/*** 无参构造*/
public CoffeeGenerator(){
}
private int size = 0;
public CoffeeGenerator(int sz){
size = sz;
}
@Override
public Coffee next(){
try {
return (Coffee)types[random.nextInt(types.length)].newInstance();
//Report programmer errors at run time. }catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
/*** 咖啡机迭代器*/
class CoffeeIterator implements Iterator{
/*** 容量*/
int count = size;
/*** 是否有下一个* @return boolean 值,只有大于0才会迭代*/
@Override
public boolean hasNext(){
return count >0;
}
/*** 下一个* @return Coffee*/
@Override
public Coffee next(){
count--;
return CoffeeGenerator.this.next();
}
/*** 移除*/
@Override
public void remove(){
throw new UnsupportedOperationException();
}
};
@Override
public Iterator iterator() {
return new CoffeeIterator();
}
public static void main(String[] args) {
CoffeeGenerator gen = new CoffeeGenerator();
for (int i = 0 ; i<5;i++){
System.out.println("next:"+gen.next());
}
for (Coffee c :new CoffeeGenerator(5)) {
System.out.println(c);
}
}
}
二、分析
1.咖啡制造器里有5种咖啡,分别是Latte, Mocha, Cappuccino, Americano,Breve;(拿铁,摩卡,卡布奇诺,美式,布雷卫半拿铁);
/**
* 所有咖啡的类型
*/
private Class[] types = {Latte.class, Mocha.class, Cappuccino.class, Americano.class,Breve.class} ;
2.定义一个随机数,47是seed值,即种子值,一般,我们使用Random是这样的:
private static Random random = new Random();
int a = random.nextInt();
因为构造Random对象时,seed默认值是系统的纳秒数,seed是伪随机数成长的一个种子,如果种子不变,最后成长的返回值也是不变的;因为系统的纳秒数目总是在不断变化的,所以随机数(其实应该叫伪随机数)的值也是在不断变化的;如果你把seed值写死了,那么返回的伪随机数就每次都是固定的,如下:
private static Random random = new Random(47);
3.无参构造,有参构造
public CoffeeGenerator(){
}
private int size = 0;
public CoffeeGenerator(int sz){
size = sz;
}
4.生产咖啡
@Override
public Coffee next(){
try {
return (Coffee)types[random.nextInt(types.length)].newInstance();
//Report programmer errors at run time. }catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
根据咖啡的种类,生产不同种的咖啡;这里的种子值seed你可以理解为一种配方;根据咖啡种类的类型,生成不同的Coffee下的具体咖啡种类;
5.咖啡机类里有一个内部类,这个类会在迭代时使用(即for循环时)
/*** 咖啡机继承迭代器,就可以循环生产咖啡了*/
class CoffeeIterator implements Iterator{
/*** 容量*/
int count = size;
/*** 是否有下一个* @return boolean 值,只有大于0才会迭代*/
@Override
public boolean hasNext(){
return count >0;
}
/*** 下一个* @return Coffee*/
@Override
public Coffee next(){
count--;
return CoffeeGenerator.this.next();
}
/*** 移除*/
@Override
public void remove(){
throw new UnsupportedOperationException();
}
};
6.咖啡机的多次生产能力核心;
@Override
public Iterator iterator() {
return new CoffeeIterator();
}
7.main方法测试;这里我们发现,两个for循环的结果不一样;
public static void main(String[] args) {
CoffeeGenerator gen = new CoffeeGenerator();
for (int i = 0 ; i<5;i++){
System.out.println("next:"+gen.next());
}
for (Coffee c :new CoffeeGenerator(5)) {
System.out.println(c);
}
}
打印结果(如果不改seed值,每次都是打印如下结果);如果你把seed值去掉;每次都会“随机”打印结果;
next:[Americano]:0
next:[Latte]:1
next:[Americano]:2
next:[Mocha]:3
next:[Mocha]:4
[Breve]:5
[Americano]:6
[Latte]:7
[Cappuccino]:8
[Cappuccino]:9
三、总结
核心技术点有两个
1.根据简单类名反射生成对象; 2.随机数 种子值得理解;
1.欢迎关注我的微信公众号:幕桥社区