泛型的基本动机:让代码适应不同的数据类型,更好地复用。比如说“容器”。
<T>
,表示泛型,中间的T就是 “类型参数”。所有的T都表示同一个类型。Holder类是个最简单的容器。用来储存和操作内部单一元素。
public class Holder<T>{
//字段
private T t;
//构造函数
public Holder(T inT){t=inT;}
//成员方法
public void set(T inT){t=inT;}
public String toString(){return t.toString();}
}
两种情况:
public static void main(String[] args){
Pet p=new Pet();
Dog d=new Dog();
Holder<Pet> h=new Holder<Pet>(p);
h.set(d);
}
和泛型类一样的用法。
public interface Generator<T>{public T next();}
语法只需要把泛型参数列表置于返回类型之前。下面例子里void后面的<T>
就是参数类型列表。
public class Test{
public static void <T> f(T t){
//do something
}
}
上面例子里的泛型方法 f(),调用的时候,不需要像泛型类那样显式的标明参数类型。
Test.f("hello");
Test.f(1);
Test.f(1.0);
当一个泛化类的内部还有一个泛化的内部类的时候,怎么处理? 看下面这个例子:
interface Interface<U>{ public U getLast();}
public class GenericsDemo<T>{
//成员字段
private List<T> content=new ArrayList<T>();
//成员方法
public void add(T t){content.add(t);}
public T getFirst(){return (content.size()>0)? content.get(0) : null;}
//!!!注意:这里不能写成Inner<T>。不然编译器会误解T代表另一个新的类型参数,而不是外部主类中的类型参数T。
class Inner implements Interface<T>{
public T getLast(){return (content.size()>0)? content.get(content.size()-1) : null;}
}
//获取内部类引用
public Interface<T> getInterface(){return this.new Inner();}
}
实用主义的描述:
如果希望外部类的类型参数 “T” 在内部类里也保持相同的含义,在声明内部函数Inner的时候,就不要再设一个
类型参数。
怎么调用上面的泛型内部类,看下面这个例子:
public static void main(String[] args){
GenericsDemo<String> gd=new GenericsDemo<String>();
gd.add("Hello World");
GenericsDemo<String>.Inner i1=gd.new Inner();
Interface<String> i2=gd.new Inner();
Interface<String> i3=gd.getInterface();
}
书里LinkedStack的例子里的内部类Node,就是一个反例,**``** 代表的是内部类自己的类型参数。
public class LinkedStack<T> {
private static class Node<U> {
U item;
Node<U> next;
Node() { item = null; next = null; }
Node(U item, Node<U> next) {
this.item = item;
this.next = next;
}
boolean end() { return item == null && next == null; }
}
//... ...
}
Java的泛型是用 “擦除” 的方式实现的。所谓擦除,就是说在运行时JVM是看到的是没有类型参数的“原生类”。比如ArrayList容器,
List<String> ls=new ArrayList<String>();
System.out.println(ls.getClass());
//Output: class java.util.ArrayList
例子里的类型参数<String>
只负责在编译期做类型检查,运行时JVM看到的是原生类“ArrayList”。
再看两个例子。第一,有一个存String和一个存Integer的ArrayList。比较他们的Class对象,类型相同。
Class c1 = new ArrayList<String>().getClass();
Class c2 = new ArrayList<Integer>().getClass();
System.out.println(c1 == c2);
// Output: true
第二个例子,我们尝试用Class#getTypeParameters()方法获得泛型的类型参数。
class A {}
public class Test {
public static void main(String[] args) {
List<A> list = new ArrayList<A>();
System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
}
}
// Output:[E]
结果返回的并不是真正的类型参数A,而是定义ArrayList
首先,和Java的擦除比,C++的模板是具体化(Reifiable)的:在编译期全展开,比如定义一个A类模板:
template<class T> class A{
public:
T g(T a,T b);
A();
};
然后定义一个A类实例。
void main(){
A<int> a;
}
对编译器来说很清楚,A<int>
类就是A<int>
。不是A<String>
。所以C++的类型很精确。
对Java来说,像下面这样,调用泛型对象的fff()方法,编译器是通不过的。因为编译器在Runtime之前,无法知道泛型T的具体类型,是否有fff()方法。
class BBB {public fff(){}}
public class AAA<T> {
T t;
public AAA(T t){this.t=t;}
public callF(){
t.fff();
}
}
后面还会讲到,Java用擦除实现泛型,会导致非常多的麻烦。为什么Java不实现像C++这样具体化的泛型,而是要用擦除?
关于这个问题,先可以看知乎上的一个问题:《Java不能实现真正泛型的原因?》。尤其是RednexelaFX的回答。 还可以参考另一个回答:《Reifiable generics与Type erasure generics各有怎样的优点与缺点?》
简单讲,首先,Java不是技术上“实现不了”。在2014的Project Valhalla里,就已经实现过。用擦除是为了 “向后兼容” 的考虑。引用Martin Odersky的原话:
泛型不是在Java1.0就有的特性。而是在Java 5才加进来的。所以Java强调的向后兼容,是 “二进制向后兼容(binary backwards compatibility)”。
也就是每一个在Java1,Java2等老版本上能正常运行的的class文件,放在Java5,6,7,8的JRE上也要正常运行。实际上在加入Java5加入泛型之前,java的类库已经经过好几年发展,有一定规模了。如果为了新泛型,把过去的类库全部推倒重来是不现实的。这就是所谓的“历史包袱”。
在这个背景下,要让老版本的没有泛型的ArrayList,在支持泛型的虚拟机上运行,擦除是最简单的办法。
还是上面这个例子,如果声明AAA类的泛型参数T的时候,加上一个 “边界”:extends BBB。编译就能通过了。因为这时候编译器会**把
class BBB {public fff(){}}
public class AAA<T extends BBB> {
T t;
public AAA(T t){this.t=t;}
public callF(){
t.fff();
}
}
Java不允许泛型数组。因为数组是强类型的,在运行时必须检测到实际数据类型,创建数组的时候必须知道数组中元素的具体类型。 具体可以参考另一篇专题:《Java为什么不支持泛型数组?》
因为数组在运行时做类型检查,所以基类数组里能存放派生类对象。这叫数组的“协变”。
Number[] numArray=new Integer[10];
一个Number数组,可以用所有Number类的派生类Integer,Long,Short,Float,Double等等的数组来为Number[]数组赋值。因为数组做运行时类型检查,不怕。
但不做运行时检查的Collection容器,比如List就不行。
List<Number> numList=new ArrayList<Integer>();
对编译器来讲,List
public class GenSet<E> {
private E[] a;
public GenSet(Class<E> c, int s) {
// Use Array native method to create array
// of a type only known at run time
@SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, s);
this.a = a;
}
E get(int i) {
return a[i];
}
}
public class GenSet<E> {
private Object[] a;
public GenSet(int s) {
a = new Object[s];
}
E get(int i) {
@SuppressWarnings("unchecked")
final E e = (E) a[i];
return e;
}
}
不能给对象数组Object[]转型。因为String[]和Object[]之间不存在IS-A的关系。
Object[] o=new Object[1];
String[] s=new String[1];
s[0]="hello";
s=(String)o;
所以,下面例子里的操作是不允许的。
public class Test<T>{
private Object[] o;
public Test3(int num){o=new Object[num];}
public void add(T t, int index){
if(index<o.length){
o[index]=t;
}
}
//单个元素转型:可以
public T get(int index){return (index<o.length)? (T)o[index] : null;}
//对数组转型:报错
public T[] getAll(){return (T[])o;} //Error
}
另一个Java擦除引起的麻烦在反省类被继承的时候发生。Java核心技术里给出下面这个例子:(参见:Java核心技术卷1:P536) 假设我有个泛型类Pair。
class Pair<T>{
private T first;
private T second;
public T getFirst(){return first;}
public void setSecond(T t){seconde=t;}
}
然后有一个表示日期区间的派生类DateInteval。它为了确保日期区间的第二个值比第一个大,重写了基类Pair的setSecond()方法。
class DateInteval extends Pair<Date>{
public void setSecond(Date d){
if(d.compareTo(getFirst())>=0){
second=d;
}
}
}
这时候就会产生一个问题,实际上DateInteval类同时具备两个setSecond方法,后面的重写的setSecond方法没有覆盖掉基类Pair的setSecond方法,因为参数类型不同。
public void setSecond(Object o); //继承自基类Pair。
public void setSecond(Date d);
如果这时候我给setSecond方法传递一个Object对象,就会错误调用继承自基类的版本。这可能不是程序员想要的。
DateInteval di=new DateInteval();
Object o=new Object();
di.setSecond(o);
所以实际上JVM在这个时候会自动合成一个 “桥方法(Bridge Method)”:
public void setSecond(Object o){setSecond((Date)o);}
这样,当我们像前面这样给setSecond传递一个Object对象的时候,会自动跳转调用正确的setSecond(Date)方法。然后因为参数类型不匹配,会抛出ClassCastException异常。
一篇IBM Developer上的文章 《Java 理论与实践: 使用通配符简化泛型使用》
<?>
<? extends XXX>
<? super XXX>
贴两张图:
具体可以参考另两篇专题:《Java泛型中extends和super的区别?》, 《通配符”?”和类型参数”T”的区别?》
PECS(Producer Extends Consumer Super)原则是要记住的:
具体细节还是参看上面两篇专题。
通过这个例子,理解一下通配符的捕获机制。
当一个通配符捕获一个运行时具体类型之后,会被标记成CAP#XXX。就不接受任何具体类型的操作。看下面这个例子感受一下。
class Ticket<T>{
private T info;
public Ticket(T t){info=t;}
public void set(T t){info=t;}
public String toString(){return info.toString();}
}
class Box<V>{
private V item;
public void set(V v){item=v;}
public String toString(){return item.toString();}
}
public class TestWildcards{
public static void main(String[] args){
/**
* Box<Ticket<?>>里什么Ticket都能放。因为通配符没有捕获类型。
*/
Box<Ticket<?>> box=new Box<Ticket<?>>();
Ticket<Integer> ti=new Ticket<Integer>(111);
Ticket<String> ts=new Ticket<String>("Hello");
box.set(ti);
System.out.println(box);
box.set(ts);
System.out.println(box);
/**
* Ticket<?>被赋值一种泛型之后,就所有的操作都不能做了。因为通配符捕获运行时实际类型后,标记为CAP#1。
*/
Ticket<?> t=new Ticket<String>("World");
//t.set(111); //ERROR, 什么类型都不接受
//t.set("what?"); //ERROR, 什么类型都不接受
System.out.println(t);
/**
* Box<Ticket<String>>里只能放Ticket<String>
*/
Box<Ticket<String>> boxTstr=new Box<Ticket<String>>();
boxTstr.set(new Ticket<String>("NoProblem"));
//boxTstr.set(new Ticket<Integer>(111)); //ERROR,编译器类型检查通不过
/**
* 同样,当通配符捕获运行时实际类型后,标记为CAP#1。就什么操作也做不了
*/
Box<? extends Ticket<?>> boxTstr2=new Box<Ticket<String>>();
//boxTstr2.set(new Ticket<String>("Now?")); //ERROR, 什么类型都不接受
//boxTstr2.set(new Ticket<Integer>(222)); //ERROR, 什么类型都不接受
}
}
下面这个例子基本把通配符常见的使用场景都包括了,遇到问题可以来查一下。
class Holder<T> {
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
public class Wildcards {
// 原生类:无泛型,就用Object代替
static void rawArgs(Holder holder, Object arg) {
//可以。raw type警告
holder.set(arg); // raw type Warning:
// 可以。raw type警告
holder.set(new Wildcards()); // raw type warning
// 不行。这里没有泛型T
//T t = holder.get();
// 可以。但原先holder里的类型信息丢失。
Object obj = holder.get();
}
// 无边界通配符
static void unboundedArg(Holder<?> holder, Object arg) {
//报错。因为Holder<capture of ?> 里的set(capture of ?)方法,代表某种不知道类型的参数,不能接受Object类型,也不接受任何类型。
//holder.set(arg); // Error:
//报错。因为Holder<capture of ?> 里的set(capture of ?)方法,代表某种不知道类型的参数,不能接受Object类型,也不接受任何类型。
//holder.set(new Wildcards()); // Same error
// 不行,没有泛型T
//T t = holder.get();
// 可以。只有Object型可以接受通配符型<?>的赋值。但原先holder里的类型信息丢失。
Object obj = holder.get();
}
// 正常泛型<T>,没问题
static <T> T exact1(Holder<T> holder) {
T t = holder.get();
return t;
}
// 正常泛型<T>,没问题
static <T> T exact2(Holder<T> holder, T arg) {
holder.set(arg);
T t = holder.get();
return t;
}
//子类边界
static <T> T wildSubtype(Holder<? extends T> holder, T arg) {
//报错。Holder<? extends T> 里的set(? extends T)方法,不能接受T类型
//holder.set(arg); // Error:
//可以。holder.get()返回T或T的子类,可以赋值给T类型。
T t = holder.get();
return t;
}
//超类边界
static <T> void wildSupertype(Holder<? super T> holder, T arg) {
//可以。因为set(? super T)接受T或T的超类为参数。无论如何都能接受T类型。
holder.set(arg);
//报错。holder.get()返回T或T的超类,无法放进T类型里。
//T t = holder.get(); // Error:
// 可以。但原先holder里的类型信息丢失。
Object obj = holder.get();
}
public static void main(String[] args) {
//Holder raw = new Holder<Long>();
// Or:
Long lng = 1L;
Object o=new Object();
//四种不同程度泛化的Holder对象
Holder raw = new Holder();
Holder<Long> qualified = new Holder<Long>();
Holder<?> unbounded = new Holder<Long>();
Holder<? extends Long> bounded = new Holder<Long>();
//原生类Holder为参数:四种Holder放进去都没问题
rawArgs(raw, lng);
rawArgs(qualified, lng);
rawArgs(unbounded, lng);
rawArgs(bounded, lng);
//无边界通配符Holder:无论放什么都不行,编译期已经报错
unboundedArg(raw, lng);
unboundedArg(qualified, lng);
unboundedArg(unbounded, lng);
unboundedArg(bounded, lng);
//警告:用Holder当Holder<T>类型参数
Object r1 = exact1(raw); // Warnings: unchecked
//没问题
Long r2 = exact1(qualified);
//只有Object可以接受<?>通配符的返回类型
Object r3 = exact1(unbounded); // Must return Object
//没问题
Long r4 = exact1(bounded);
//警告:用Holder当Holder<Long>
Long r5 = exact2(raw, lng); // Warnings: unchecked
//没问题
Long r6 = exact2(qualified, lng);
//报错:exact2(Holder<T>,T)方法不能用(Holder<capture of ?>,Long)这两个参数。
Long r7 = exact2(unbounded, lng); // Error:
//报错:exact2(Holder<T>,T)方法不能用(Holder<capture of ? extends Long>,Long)这两个参数。
Long r8 = exact2(bounded, lng); // Error:
//警告:改用holder<Long>的地方用了holder原生类
Long r9 = wildSubtype(raw, lng); // Warnings: unchecked
//警告:该给(Holder<? extends T>,T)参数的,给了(Holder,Long)
Long r10 = wildSubtype(qualified, lng);
//没问题,但只能用Object来接收返回值
Object r11 = wildSubtype(unbounded, lng);
//没问题
Long r12 = wildSubtype(bounded, lng);
//警告:该给(Holder<? super T>,T)参数的,给了(Holder,Long)
wildSupertype(raw, lng); // Warnings:
//没问题
wildSupertype(qualified, lng);
//报错:该给(Holder<? super T>,T)参数的,给了(Holder<capture of ?>,Long)
wildSupertype(unbounded, lng); // Error:
//报错:该给(Holder<? super T>,T)参数的,给了(Holder<capture of ? extends Long>,Long)
wildSupertype(bounded, lng); // Error:
}
}
使用一个泛型类Plate<T>
,如果用无界通配符Plate<?>
,就可以放各种不同的类型。每存入一个类型,都会临时命名为CAP#XXX。
所以List<Plate<?>>
里什么Plate都能放。
interface Fruit{public String toString();}
class Apple implements Fruit{public String toString(){return "Apple!";}}
class Banana implements Fruit{public String toString(){return "Banana!";}}
class Melon implements Fruit{public String toString(){return "Melon!";}}
class Plate<T>{
private T item;
public Plate(T t){item=t;}
public String toString(){return "A plate of "+item;}
}
public class WildBox<T>{
private List<T> list=new ArrayList<T>();
public void add(T t){list.add(t);}
public T get(int index){return (index<list.size())? list.get(index):null;}
public static void main(String[] args){
WildBox<Plate<?>> wb=new WildBox<Plate<?>>();
wb.add(new Plate<Apple>(new Apple()));
wb.add(new Plate<Banana>(new Banana()));
System.out.println(wb.get(0));
System.out.println(wb.get(1));
}
}
//Output:
//A plate of Apple!
//A plate of Banana!
但判断Set<Plate<?>>
里都有什么Plate,都是false。体会一下通配符的捕获机制。
interface Fruit{public String toString();}
class Apple implements Fruit{public String toString(){return "Apple!";}}
class Banana implements Fruit{public String toString(){return "Banana!";}}
class Melon implements Fruit{public String toString(){return "Melon!";}}
class Plate<T>{
private T item;
public Plate(T t){item=t;}
public String toString(){return "A plate of "+item;}
}
public class WildBox2<T>{
private Set<T> set=new HashSet<T>();
public void add(T t){set.add(t);}
public boolean contains(T t){return set.contains(t);}
public static void main(String[] args){
WildBox2<Plate<?>> wb=new WildBox2<Plate<?>>();
wb.add(new Plate<Apple>(new Apple()));
wb.add(new Plate<Banana>(new Banana()));
System.out.println(wb.contains(new Plate<Apple>(new Apple())));
System.out.println(wb.contains(new Plate<Banana>(new Banana())));
System.out.println(wb.contains(new Plate<Melon>(new Melon())));
}
}
根据Override重写的规则,被重写方法的参数和返回值都不能变。
Java 5.0开始允许在派生类中继承自基类的方法改变返回值。
class Base {}
class Derived extends Base {}
interface OrdinaryGetter {
Base get();
}
interface DerivedGetter extends OrdinaryGetter {
// Return type of overridden method is allowed to vary:
Derived get();
}
“古怪的循环泛型”的本质就是:“基类用导出类作为类型参数”。
class BaseGeneric<T> {}
class SubType extends BaseGeneric<SubType> {}
这种循环泛型的好处是,泛型基类BaseGeneric里定义的方法,是以其自身的导出类SubType为参数,和返回值。所以SubType类所继承的方法都是以同类SubType的其他对象实例为参数和返回值。所以,泛型基类BaseGeneric相当于定义了针对它自身导出类的一系列操作。然后它的导出类就只能操作自己的同类对象。这是循环泛型的意义所在。
但上面的例子只是说SubType使用了循环泛型的用法。但泛型基类BaseGeneric的其他子类完全可以不使用循环泛型。
所以自限定的意义就在于,在定义泛型基类的时候,强制这个泛型基类的导出类,只能使用循环泛型的形式。
class SelfBounds<T extends SelfBounds<T>> {}
自限定类型最典型的应用:Enum枚举型 一定要看这篇关于枚举型的文章–《Java 语言中 Enum 类型的使用介绍》
Getter g的g.get()方法的返回值是派生类Getter类型,而不是基类GenericGetter类型。而且和普通的继承规则不同,g.get()方法不是被重载(overload)而是重写(override)。
interface GenericGetter<T extends GenericGetter<T>> {
T get();
}
interface Getter extends GenericGetter<Getter> {}
public class GenericsAndReturnTypes {
void test(Getter g) {
Getter result = g.get();
GenericGetter gg = g.get(); // Also the base type
}
}
想要抛出根据泛型变化的异常,就需要把异常当成类型参数写进函数里。然后由throws关键字抛出。看下面这个例子:
interface Processor<T,E extends Exception, F extends Exception> {
public void process(List<T> resultCollector) throws E,F;
}
class ProcessRunner<T,E extends Exception, F extends Exception> extends ArrayList<Processor<T,E,F>> {
private static final long serialVersionUID=0;
public List<T> processAll() throws E,F {
List<T> resultCollector = new ArrayList<T>();
for(Processor<T,E,F> processor : this){
processor.process(resultCollector);
}
return resultCollector;
}
}
潜在类型机制也叫“鸭子类型机制”。大白话说就是:我不用定义一个关于方法a()和方法b()的接口。我可以不关心类型,只要有a()方法和b()方法就行。
Python里可以有这样的代码:
class Dog:
def speak(self):
print "Arf!"
def sit(self):
print "Sitting"
def reproduce(self):
pass
class Robot:
def speak(self):
print "Click!"
def sit(self):
print "Clank!"
def oilChange(self) :
pass
def perform(anything):
anything.speak()
anything.sit()
C++里可以这样写:
class Dog {
public:
void speak() {}
void sit() {}
void reproduce() {}
};
class Robot {
public:
void speak() {}
void sit() {}
void oilChange() {
};
template<class T> void perform(T anything) {
anything.speak();
anything.sit();
}
Java泛型的先天不足,可以用模式来弥补。下面的例子用适配器模式,模拟出一个“潜在类型”。
//addable接口
interface Addable<T> { void add(T t); }
//面向Addable接口的fill方法
class FillPets {
//用反射填充容器
public static <T extends Pet> void fill(Addable<T> addable, Class<? extends T> classToken, int size) {
for(int i = 0; i < size; i++){
try {
addable.add(classToken.newInstance());
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
}
/** 《适配器》
* 原理是类库里的Collection和SimpleQueue动不了。
* 那就给他们都套一层代理。然后新的代理类实现Addable接口。
*/
//Collection是通过组合的方式套代理
class AddableCollectionAdapter<T> implements Addable<T> {
private Collection<T> c;
public AddableCollectionAdapter(Collection<T> c) {
this.c = c;
}
public void add(T item) { c.add(item); }
}
// 把加了add()方法的容器的引用,赋值给Addable接口。
class Adapter {
public static <T> Addable<T> collectionAdapter(Collection<T> c) {
return new AddableCollectionAdapter<T>(c);
}
}
//SimpleQueue
class SimpleQueue<T> implements Iterable<T> {
private LinkedList<T> storage = new LinkedList<T>();
public void add(T t) { storage.offer(t); }
public T get() { return storage.poll(); }
public Iterator<T> iterator() {
return storage.iterator();
}
}
//SimpleQueue的派生类实现Addable接口。
class AddableSimpleQueue<T> extends SimpleQueue<T> implements Addable<T> {
public void add(T item) { super.add(item); }
}
/**
* LEV 1
*/
class Individual{
private String name;
public Individual(){this.name="NULL";}
public Individual(String name){this.name=name;}
public void speak(){System.out.println("...");}
}
/**
* LEV 2
*/
class Person extends Individual {
public Person(String name) { super(name); }
@Override
public void speak(){System.out.println("Hello World!");}
}
class Pet extends Individual {
public Pet(String name) { super(name); }
public Pet() { super(); }
@Override
public void speak(){System.out.println("!!!");}
}
/**
* LEV 3 - 狗,猫,鼠
*/
class Dog extends Pet {
public Dog(String name) { super(name); }
public Dog() { super(); }
@Override
public void speak(){System.out.println("WongWong!!!");}
}
class Cat extends Pet {
public Cat(String name) { super(name); }
public Cat() { super(); }
@Override
public void speak(){System.out.println("MiewMiew!!!");}
}
class Rodent extends Pet {
public Rodent(String name) { super(name); }
public Rodent() { super(); }
@Override
public void speak(){System.out.println("JiJiJi!!!");}
}
/**
* LEV 4 - 狗系
*/
class Mutt extends Dog {
public Mutt(String name) { super(name); }
public Mutt() { super(); }
}
class Pug extends Dog {
public Pug(String name) { super(name); }
public Pug() { super(); }
}
/**
* LEV 4 - 猫系
*/
class EgyptianMau extends Cat {
public EgyptianMau(String name) { super(name); }
public EgyptianMau() { super(); }
}
class Manx extends Cat {
public Manx(String name) { super(name); }
public Manx() { super(); }
}
/**
* LEV 4 - 鼠系
*/
class Rat extends Rodent {
public Rat(String name) { super(name); }
public Rat() { super(); }
}
class Mouse extends Rodent {
public Mouse(String name) { super(name); }
public Mouse() { super(); }
}
class Hamster extends Rodent {
public Hamster(String name) { super(name); }
public Hamster() { super(); }
}
* 测试类
*/
public class Exercise41{
public static void main(String[] args){
//Pet容器
List<Dog> dogs=new ArrayList<Dog>();
//给Pet容器套上实现了Addable接口的适配器,就能用面向Addable接口的fill()方法了。
Fill2.fill(new AddableCollectionAdapter<Dog>(dogs),Mutt.class, 3);
//用辅助方法获得Addable接口对象实例
Fill2.fill(Adapter.collectionAdapter(dogs), Pug.class, 2);
for(Dog d: dogs){
d.speak();
}
System.out.println("----------------------");
//SimpleQueue实现了Addable()接口与的派生类。也可以用fill()方法填充。
AddableSimpleQueue<Cat> catQueue = new AddableSimpleQueue<Cat>();
Fill2.fill(catQueue, EgyptianMau.class, 4);
Fill2.fill(catQueue, Manx.class, 1);
for(Cat c: catQueue){
c.speak();
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
class Pet{public String toString(){return "A Pet!";}}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
class Dog extends Pet{public String toString(){return "A Dog!";}}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
class Cat extends Pet{public String toString(){return "A Cat!";}}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise1<T>{
private T t1;
private T t2;
private T t3;
public Exercise1(T one,T two,T three){t1=one;t2=two;t3=three;}
public List<T> get(){
return Arrays.asList(t1,t2,t3);
}
public String toString(){return "["+t1.toString()+"],"+"["+t2.toString()+"],"+"["+t3.toString()+"]";}
public static void main(String[] args){
Pet p=new Pet();
Dog d=new Dog();
Cat c=new Cat();
Exercise1<Pet> h=new Exercise1<Pet>(p,d,c);
System.out.println(h);
List<Pet> l=h.get();
for(int i=0;i<l.size();i++){
System.out.println(l.get(i));
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
class Pet{public String toString(){return "A Pet!";}}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
class Dog extends Pet{public String toString(){return "A Dog!";}}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
class Cat extends Pet{public String toString(){return "A Cat!";}}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise2<T>{
private T t1;
private T t2;
private T t3;
public Exercise2(T one,T two,T three){t1=one;t2=two;t3=three;}
public List<T> get(){
return Arrays.asList(t1,t2,t3);
}
public String toString(){return "["+t1.toString()+"],"+"["+t2.toString()+"],"+"["+t3.toString()+"]";}
public static void main(String[] args){
Pet p=new Pet();
Dog d=new Dog();
Cat c=new Cat();
Exercise2<Pet> h=new Exercise2<Pet>(p,d,c);
System.out.println(h);
List<Pet> l=h.get();
for(int i=0;i<l.size();i++){
System.out.println(l.get(i));
}
}
}
class Exercise3<A,B,C,D,E,F>{ A a; B b; C c; D d; E e; F f;
public Exercise3(A inA,B inB,C inC,D inD,E inE,F inF){a=inA;b=inB;c=inC;d=inD;e=inE;f=inF;}
public String toString(){return a.toString()+b.toString()+c.toString()+d.toString()+e.toString()+f.toString();}
public static void main(String[] args){
Exercise3<Integer,Long,Float,Double,String,Boolean> mySix=new Exercise3<Integer,Long,Float,Double,String,Boolean>(1,2l,3f,4d,"five",true);
System.out.println(mySix.toString());
} } ```
package com.ciaoshen.thinkinjava.chapter15;
public interface Selector<T> {
boolean end();
T current();
void next();
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise4<T> {
private List<T> items;
private int next = 0;
public Exercise4() { items = new ArrayList<T>(); }
public void add(T x) {
items.add(x);
}
public String toString(){
String r="";
for(T item : items){
r+=item;
}
return r;
}
private class SequenceSelector implements Selector<T> {
private int i = 0;
public boolean end() { return i == items.size(); }
public T current() { return items.get(i); }
public void next() { if(i < items.size()){i++;} }
}
public Selector<T> selector() {
return new SequenceSelector();
}
public static void main(String[] args) {
Exercise4<String> sequence = new Exercise4<String>();
for(int i = 0; i < 10; i++){
sequence.add(Integer.toString(i));
}
System.out.println(sequence);
Selector<String> selector = sequence.selector();
while(!selector.end()) {
System.out.print(selector.current() + " ");
selector.next();
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise5<T> {
private class Node {
T item;
Node next;
Node() { item = null; next = null; }
Node(T item, Node next) {
this.item = item;
this.next = next;
}
boolean end() { return item == null && next == null; }
}
private Node top = new Node(); // End sentinel
public void push(T item) {
top = new Node(item, top);
}
public T pop() {
T result = top.item;
if(!top.end())
top = top.next;
return result;
}
public static void main(String[] args) {
Exercise5<String> test= new Exercise5<String>();
for(String s : "Phasers on stun!".split(" ")){
test.push(s);
}
String s;
while((s=test.pop()) != null){
System.out.println(s);
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise6<T> {
private ArrayList<T> storage = new ArrayList<T>();
private Random rand = new Random();
public void add(T item) { storage.add(item); }
public T select() {
return storage.get(rand.nextInt(storage.size()));
}
public static void main(String[] args) {
Exercise6<String> rs = new Exercise6<String>();
Exercise6<Integer> ri=new Exercise6<Integer>();
Exercise6<Float> rf=new Exercise6<Float>();
for(String s: ("The quick brown fox jumped over " + "the lazy brown dog").split(" ")){
rs.add(s);
}
for(int i = 0; i < 11; i++){
System.out.print(rs.select() + " ");
}
for(int i=0;i<10;i++){
ri.add(i);
rf.add((float)i);
}
for(int i=0;i<10;i++){
System.out.println(ri.select());
System.out.println(rf.select());
}
}
}
这题的关键在于实现两个接口。外部类IterableFibonacci实现Iterable
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Fibonacci{
public Integer next() { return fib(count++); }
private int count = 0;
private int fib(int n) {
if(n < 2) return 1;
return fib(n-2) + fib(n-1);
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise7 extends Fibonacci implements Iterable<Integer>{
private int n;
public Exercise7(int count) { n = count; }
public Iterator<Integer> iterator(){return this.new FibIte();}
class FibIte implements Iterator<Integer>{
private int count=0;
public boolean hasNext() { return n > 0; }
public Integer next() {
n--;
return Exercise7.this.next();
}
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
}
public static void main(String[] args) {
Exercise7 iteFib=new Exercise7(18);
Iterator<Integer> ite=iteFib.iterator();
while(ite.hasNext()){
System.out.print(ite.next()+" ");
}
System.out.println();
}
}
package com.ciaoshen.thinkinjava.chapter15;
public interface Generator<T>{
public T next();
}
package com.ciaoshen.thinkinjava.chapter15;
public class GoodGuys extends StoryCharacters{
public GoodGuys(){
super("Good "+String.valueOf(System.nanoTime()));
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class BadGuys extends StoryCharacters{
public BadGuys(){
super("Bad "+String.valueOf(System.nanoTime()));
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class StoryCharacters{
public String name;
public StoryCharacters(String inName){name=inName;}
public String toString(){return name;}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise8 implements Generator<StoryCharacters>, Iterable<StoryCharacters> {
private static List<Class<? extends StoryCharacters>> factories=new ArrayList<Class<? extends StoryCharacters>>();
private static Random rand=new Random();
static{
factories.add(GoodGuys.class);
factories.add(BadGuys.class);
}
private int max;
public Exercise8(int inNum){max=inNum;}
public Iterator<StoryCharacters> iterator(){return this.new ChIte(max);}
public StoryCharacters next(){
try{
return (StoryCharacters)(factories.get(rand.nextInt(factories.size())).newInstance());
}catch(Exception e){
System.out.println("Cannot make the new instance of StoryCharacters!");
return null;
}
}
class ChIte implements Iterator<StoryCharacters>{
private int n;
public ChIte(int num){n=num;}
public boolean hasNext(){return n>0;}
public StoryCharacters next(){
n--;
return Exercise8.this.next();
}
public void remove(){
throw new UnsupportedOperationException();
}
}
public static void main(String[] args) {
Exercise8 test=new Exercise8(10);
Iterator<StoryCharacters> ite=test.iterator();
while(ite.hasNext()){
System.out.println(ite.next());
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise9{
public <T,U,V> void f(T t, U u, V v) {
System.out.println(t.getClass().getName());
System.out.println(u.getClass().getName());
System.out.println(v.getClass().getName());
}
public static void main(String[] args) {
Exercise9 test= new Exercise9();
test.f("",1,1.0);
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise10{
public <T,U> void f(T t, U u, String s) {
System.out.println(t.getClass().getName());
System.out.println(u.getClass().getName());
System.out.println(s.getClass().getName());
}
public static void main(String[] args) {
Exercise10 test= new Exercise10();
test.f(1,1.0,"2.0");
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class GenericOne<T>{
private T t;
public GenericOne(T inT){t=inT;}
public String toString(){return t.toString()+": "+ t.getClass().getName();}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise11{
public static <T> GenericOne<T> getOne(T inT){return new GenericOne<T>(inT);}
public static void main(String[] args){
GenericOne<String> go= Exercise11.getOne("Hello");
System.out.println(go);
GenericOne<Integer> gi = Exercise11.getOne(100);
System.out.println(gi);
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class GenericOne<T>{
private T t;
public GenericOne(T inT){t=inT;}
public String toString(){return t.toString()+": "+ t.getClass().getName();}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise12{
public static <T> GenericOne<T> getOne(T inT){return new GenericOne<T>(inT);}
public static void main(String[] args){
GenericOne<String> go= Exercise12.<String>getOne("Hello");
System.out.println(go);
GenericOne<Integer> gi = Exercise12.<Integer>getOne(100);
System.out.println(gi);
}
}
package com.ciaoshen.thinkinjava.chapter15;
public interface Generator<T>{
public T next();
}
package com.ciaoshen.thinkinjava.chapter15;
public class Coffee{
private static long count;
private long id;
public Coffee(){id=count++;}
public long showId(){return id;}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Latte extends Coffee{
public String toString(){return "No."+String.valueOf(showId())+">>> I am Latte!";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Mocha extends Coffee{
public String toString(){return "No."+String.valueOf(showId())+">>> I am Mocha!";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Capuccino extends Coffee{
public String toString(){return "No."+String.valueOf(showId())+">>> I am Capuccino!";}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class CoffeeGenerator implements Generator<Coffee>{
private static List<Class<? extends Coffee>> c=new ArrayList<Class<? extends Coffee>>();
static{
c.add(Latte.class);
c.add(Mocha.class);
c.add(Capuccino.class);
}
private Random rand=new Random();
public Coffee next(){
int i=rand.nextInt(c.size());
try{
return c.get(i).newInstance();
}catch(Exception e){
System.out.println(e);
return null;
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise13{
public static <T> Collection<T> fill(Collection<T> coll, Generator<T> gen, int n) {
for(int i = 0; i < n; i++){
coll.add(gen.next());
}
return coll;
}
public static <T> List<T> fill(List<T> list, Generator<T> gen, int n){
for(int i=0;i<n;i++){
list.add(gen.next());
}
return list;
}
public static <T> Queue<T> fill(Queue<T> queue, Generator<T> gen, int n){
for(int i=0;i<n;i++){
queue.add(gen.next());
}
return queue;
}
public static <T> Set<T> fill(Set<T> set, Generator<T> gen, int n){
for(int i=0;i<n;i++){
set.add(gen.next());
}
return set;
}
public static void main(String[] args) {
List<Coffee> manyCoffee=new ArrayList<Coffee>();
manyCoffee=Exercise13.fill(manyCoffee, new CoffeeGenerator(), 10);
for(Coffee cup : manyCoffee){
System.out.println(cup);
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
public interface Generator<T>{
public T next();
}
package com.ciaoshen.thinkinjava.chapter15;
public class CountedObject {
private static long counter = 0;
private final long id = counter++;
public long id() { return id; }
public String toString() { return "CountedObject " + id;}
}
package com.ciaoshen.thinkinjava.chapter15;
public class BasicGenerator<T> implements Generator<T> {
private Class<T> type;
public BasicGenerator(Class<T> type){ this.type = type; }
public T next() {
try {
// Assumes type is a public class:
return type.newInstance();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
// Produce a Default generator given a type token:
public static <T> Generator<T> create(Class<T> type) {
return new BasicGenerator<T>(type);
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise14{
public static void main(String[] args) {
BasicGenerator<CountedObject> bg=new BasicGenerator<CountedObject>(CountedObject.class);
for(int i = 0; i < 5; i++)
System.out.println(bg.next());
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class TwoTuple<A,B>{
private final A first;
private final B second;
public TwoTuple(A a,B b){first=a;second=b;}
public String toString(){return "["+first+","+second+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class ThreeTuple<A,B,C>{
private final A first;
private final B second;
private final C third;
public ThreeTuple(A a,B b,C c){first=a;second=b;third=c;}
public String toString(){return "["+first+","+second+","+third+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class FourTuple<A,B,C,D>{
private final A first;
private final B second;
private final C third;
private final D fourth;
public FourTuple(A a,B b,C c,D d){first=a;second=b;third=c;fourth=d;}
public String toString(){return "["+first+","+second+","+third+","+fourth+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class FiveTuple<A,B,C,D,E>{
private final A first;
private final B second;
private final C third;
private final D fourth;
private final E fifth;
public FiveTuple(A a,B b,C c,D d,E e){first=a;second=b;third=c;fourth=d;fifth=e;}
public String toString(){return "["+first+","+second+","+third+","+fourth+","+fifth+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class SixTuple<A,B,C,D,E,F>{
private final A first;
private final B second;
private final C third;
private final D fourth;
private final E fifth;
private final F sixth;
public FiveTuple(A a,B b,C c,D d,E e,F f){first=a;second=b;third=c;fourth=d;fifth=e;sixth=f;}
public String toString(){return "["+first+","+second+","+third+","+fourth+","+fifth+","+sixth+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Tuple{
public static <A,B> TwoTuple<A,B> tuple(A a, B b) {
return new TwoTuple<A,B>(a, b);
}
public static <A,B,C> ThreeTuple<A,B,C> tuple(A a, B b, C c) {
return new ThreeTuple<A,B,C>(a, b, c);
}
public static <A,B,C,D> FourTuple<A,B,C,D> tuple(A a, B b, C c, D d) {
return new FourTuple<A,B,C,D>(a, b, c, d);
}
public static <A,B,C,D,E> FiveTuple<A,B,C,D,E> tuple(A a, B b, C c, D d, E e) {
return new FiveTuple<A,B,C,D,E>(a, b, c, d, e);
}
public static <A,B,C,D,E,F> SixTuple<A,B,C,D,E,F> tuple(A a, B b, C c, D d, E e, F f) {
return new SixTuple<A,B,C,D,E,F>(a, b, c, d, e, f);
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise15{
public static void main(String[] args){
@SuppressWarnings("rawtypes")
TwoTuple tuple=Tuple.tuple("ABC",123);
System.out.println(tuple);
//@SuppressWarnings("unchecked") //不加注释就会报unchecked警告
TwoTuple<String,Integer> withType=tuple;
System.out.println(withType);
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class TwoTuple<A,B>{
private final A first;
private final B second;
public TwoTuple(A a,B b){first=a;second=b;}
public String toString(){return "["+first+","+second+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class ThreeTuple<A,B,C>{
private final A first;
private final B second;
private final C third;
public ThreeTuple(A a,B b,C c){first=a;second=b;third=c;}
public String toString(){return "["+first+","+second+","+third+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class FourTuple<A,B,C,D>{
private final A first;
private final B second;
private final C third;
private final D fourth;
public FourTuple(A a,B b,C c,D d){first=a;second=b;third=c;fourth=d;}
public String toString(){return "["+first+","+second+","+third+","+fourth+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class FiveTuple<A,B,C,D,E>{
private final A first;
private final B second;
private final C third;
private final D fourth;
private final E fifth;
public FiveTuple(A a,B b,C c,D d,E e){first=a;second=b;third=c;fourth=d;fifth=e;}
public String toString(){return "["+first+","+second+","+third+","+fourth+","+fifth+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class SixTuple<A,B,C,D,E,F>{
private final A first;
private final B second;
private final C third;
private final D fourth;
private final E fifth;
private final F sixth;
public FiveTuple(A a,B b,C c,D d,E e,F f){first=a;second=b;third=c;fourth=d;fifth=e;sixth=f;}
public String toString(){return "["+first+","+second+","+third+","+fourth+","+fifth+","+sixth+"]";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Tuple{
public static <A,B> TwoTuple<A,B> tuple(A a, B b) {
return new TwoTuple<A,B>(a, b);
}
public static <A,B,C> ThreeTuple<A,B,C> tuple(A a, B b, C c) {
return new ThreeTuple<A,B,C>(a, b, c);
}
public static <A,B,C,D> FourTuple<A,B,C,D> tuple(A a, B b, C c, D d) {
return new FourTuple<A,B,C,D>(a, b, c, d);
}
public static <A,B,C,D,E> FiveTuple<A,B,C,D,E> tuple(A a, B b, C c, D d, E e) {
return new FiveTuple<A,B,C,D,E>(a, b, c, d, e);
}
public static <A,B,C,D,E,F> SixTuple<A,B,C,D,E,F> tuple(A a, B b, C c, D d, E e, F f) {
return new SixTuple<A,B,C,D,E,F>(a, b, c, d, e, f);
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Vehicle{
private static int count=0;
private int id=++count;
public String toString(){return "Vehicle#"+id;}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Amphibian{
private static int count=0;
private int id=++count;
public String toString(){return "Amphibian#"+id;}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise16{
static TwoTuple<String,Integer> f() {
return Tuple.tuple("hi", 47);
}
@SuppressWarnings("rawtypes")
static TwoTuple f2() { return Tuple.tuple("hi", 47); }
static ThreeTuple<Amphibian,String,Integer> g() {
return Tuple.tuple(new Amphibian(), "hi", 47);
}
static FourTuple<Vehicle,Amphibian,String,Integer> h() {
return Tuple.tuple(new Vehicle(), new Amphibian(), "hi", 47);
}
static FiveTuple<Vehicle,Amphibian,String,Integer,Double> k() {
return Tuple.tuple(new Vehicle(), new Amphibian(), "hi", 47, 11.1);
}
static SixTuple<Vehicle,Amphibian,String,Integer,Double,Float> l() {
return Tuple.tuple(new Vehicle(), new Amphibian(), "hi", 47, 11.1,22.2f);
}
public static void main(String[] args) {
TwoTuple<String,Integer> ttsi = f();
System.out.println(ttsi);
System.out.println(f2());
System.out.println(g());
System.out.println(h());
System.out.println(k());
System.out.println(l());
}
}
这道题关键是练习泛型方法怎么声明:
**public static <T extends Enum
> EnumSet union(EnumSet a, EnumSet b) {... ...}**
注意! 在函数的参数以及返回值的地方直接用泛型替换符T来表示,但是在最前面参数列表的地方,要定义参数T的具体边界。
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
import java.lang.reflect.*;
public class Exercise17 {
private static enum Watercolors { ZINC, LEMON_YELLOW, MEDIUM_YELLOW, DEEP_YELLOW, ORANGE, BRILLIANT_RED, CRIMSON, MAGENTA, ROSE_MADDER, VIOLET, CERULEAN_BLUE_HUE, PHTHALO_BLUE, ULTRAMARINE, COBALT_BLUE_HUE, PERMANENT_GREEN, VIRIDIAN_HUE, SAP_GREEN, YELLOW_OCHRE, BURNT_SIENNA, RAW_UMBER, BURNT_UMBER, PAYNES_GRAY, IVORY_BLACK }
public static <T extends Enum<T>> EnumSet<T> union(EnumSet<T> a, EnumSet<T> b) {
EnumSet<T> result = a.clone();
result.addAll(b);
return result;
}
public static <T extends Enum<T>> EnumSet<T> intersection(EnumSet<T> a, EnumSet<T> b) {
EnumSet<T> result = a.clone();
result.retainAll(b);
return result;
}
public static <T extends Enum<T>> EnumSet<T> difference(EnumSet<T> superset, EnumSet<T> subset) {
EnumSet<T> result = superset.clone();
result.removeAll(subset);
return result;
}
public static <T extends Enum<T>> EnumSet<T> complement(EnumSet<T> a, EnumSet<T> b) {
return difference(union(a, b), intersection(a, b));
}
public static void main(String[] args){
EnumSet<Watercolors> set1=EnumSet.range(Watercolors.MEDIUM_YELLOW, Watercolors.MAGENTA);
EnumSet<Watercolors> set2=EnumSet.range(Watercolors.ZINC,Watercolors.ORANGE);
EnumSet<Watercolors> setUnion=Sets.union(set1,set2);
EnumSet<Watercolors> setIntersection=Sets.intersection(set1,set2);
EnumSet<Watercolors> setComplement=Sets.complement(set1,set2);
EnumSet<Watercolors> superset=EnumSet.range(Watercolors.ZINC,Watercolors.PERMANENT_GREEN);
EnumSet<Watercolors> subset=EnumSet.range(Watercolors.CRIMSON, Watercolors.ULTRAMARINE);
EnumSet<Watercolors> setDifference=Sets.difference(superset,subset);
System.out.println("\n Set Union >>>>>");
for(Watercolors w : setUnion){
System.out.print(w+" ");
}
System.out.println("\n Set Intersection >>>>>");
for(Watercolors w : setIntersection){
System.out.print(w+" ");
}
System.out.println("\n Set Complement >>>>>");
for(Watercolors w : setComplement){
System.out.print(w+" ");
}
System.out.println("\n Set Difference >>>>>");
for(Watercolors w : setDifference){
System.out.print(w+" ");
}
}
}
public interface Generator<T>{public T next();}
package com.ciaoshen.thinkinjava.chapter15;
public class SmallFish{
private static long counter=1;
private final long id=counter++;
private SmallFish(){}
public String toString(){return "Small Fish No."+id;}
public static Generator<SmallFish> generator(){
return new Generator<SmallFish>(){
public SmallFish next(){
return new SmallFish();
}
};
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class BigFish{
private static long counter=1;
private final long id=counter++;
private BigFish(){}
public String toString(){return "Big Fish No."+id;}
public static Generator<BigFish> generator(){
return new Generator<BigFish>(){
public BigFish next(){
return new BigFish();
}
};
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
import java.lang.reflect.*;
public class Exercise18{
public static void eat(BigFish bf, SmallFish sf){
System.out.println(bf+" EAT "+sf);
}
public static void main(String[] args){
Random rand=new Random();
Queue<SmallFish> foods=new LinkedList<SmallFish>();
for(int i=0;i<15;i++){
foods.add(SmallFish.generator().next());
}
List<BigFish> killers=new ArrayList<BigFish>();
for(int i=0;i<4;i++){
killers.add(BigFish.generator().next());
}
for(SmallFish sf:foods){
Exercise18.eat(killers.get(rand.nextInt(killers.size())),sf);
}
}
}
interface Generator<T>{public T next();}
public class Generators{
public static <T> void fill(List<T> list, Generator<T> gen, int num){
for(int i=0;i<num;i++){
list.add(gen.next());
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Product {
private static long count=0;
private final long id=++count;
private double price;
public Product(double price){
this.price = price;
}
public String toString() {
return " Product No."+id + " >>> " + "price: $" + price;
}
public static Generator<Product> generator = new Generator<Product>() {
private Random rand = new Random();
public Product next() {
return new Product( Math.round(rand.nextDouble() * 1000.0) + 0.99);
}
};
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Container extends ArrayList<Product>{
private static final long serialVersionUID=0;
private static final int MAX_SIZE=1000;
private static long count=0;
private final long id=++count;
private final int size;
public Container(int max){
super();
size=max;
}
public void fill(int numP){
Generators.fill(this,Product.generator,Math.min(size,numP));
}
public String toString(){
StringBuilder s=new StringBuilder();
s.append(" Container No."+id+"[Max Size: "+size+"] >>> \n");
for(Product p:this){
s.append(p+"\n");
}
return s.toString();
}
public static Generator<Container> generator = new Generator<Container>(){
Random rand=new Random();
public Container next(){
return new Container(rand.nextInt(MAX_SIZE));
}
};
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Deck extends ArrayList<Container>{
private static final long serialVersionUID=0;
private static final int MAX_SIZE=10000;
private static long count=0;
private final long id=++count;
private final int size;
private Deck(int max){
super();
size=max;
}
public void fill(int numC, int numP){
Generators.fill(this, Container.generator, Math.min(size,numC));
for(Container c:this){
c.fill(numP);
}
}
public String toString(){
StringBuilder s=new StringBuilder();
s.append("Deck No."+id+"[Max Size: "+size+"] >>> \n");
for(Container c:this){
s.append(c+"\n");
}
return s.toString();
}
public static Generator<Deck> generator=new Generator<Deck>(){
Random rand=new Random();
public Deck next(){
return new Deck(rand.nextInt(MAX_SIZE));
}
};
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class CargoShip extends ArrayList<Deck> {
private static final long serialVersionUID=0;
private static final int MAX_SIZE=20;
public CargoShip(int numD, int numC, int numP) {
Generators.fill(this,Deck.generator,Math.min(numD,MAX_SIZE));
for(Deck d:this){
d.fill(numC,numP);
}
}
public String toString() {
StringBuilder result = new StringBuilder();
for(Deck d : this){
result.append(d+"\n");
}
return result.toString();
}
public static void main(String[] args) {
System.out.println(new CargoShip(5,5,5));
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise19{
public static void main(String[] args){
System.out.println(new CargoShip(2,2,2));
}
}
package com.ciaoshen.thinkinjava.chapter15;
public interface I{
public void a();
public void b();
}
package com.ciaoshen.thinkinjava.chapter15;
public class Impl implements I{
public void a(){System.out.println("I am a()!");}
public void b(){System.out.println("I am b()!");}
public void c(){System.out.println("I am c()!");}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise20{
public static <T extends I> void generic(T t){
t.a();
t.b();
}
public static void main(String[] args){
Exercise20.generic(new Impl());
}
}
这题需要注意的是:Map<String,Class<?» typeMap=new HashMap<String,Class<?»(); 这样带通配符的赋值方法竟然可以。也就是Map里可以存不同泛型的Class对象。证明JAVA的泛型是编译时泛型,运行时擦除。
package com.ciaoshen.thinkinjava.chapter15;
public class Building {public Building(){System.out.println("I am Building!");}}
package com.ciaoshen.thinkinjava.chapter15;
public class House extends Building {public House(){System.out.println("I am House!");}}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class ClassTypeCapture {
private Map<String,Class<?>> typeMap=new HashMap<String,Class<?>>();
public void addType(String key, Class<?> value){
typeMap.put(key,value);
}
public Object createNew(String name){
Class<?> c=typeMap.get(name);
try{
Object o=c.newInstance();
return o;
}catch(Exception e){
System.out.println(e);
return null;
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise21{
public static void main(String[] args){
ClassTypeCapture ctc=new ClassTypeCapture();
ctc.addType("Building",Building.class);
ctc.addType("House",House.class);
ctc.createNew("Building");
}
}
package com.ciaoshen.thinkinjava.chapter15;
public interface Fruit{public String toString();}
package com.ciaoshen.thinkinjava.chapter15;
public class Apple implements Fruit{
private String color;
public Apple(String color){this.color=color;}
public String toString(){return "A "+color+" Apple!";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Banana implements Fruit{
private String color;
public Banana(String color){this.color=color;}
public String toString(){return "A "+color+" Banana!";}
}
package com.ciaoshen.thinkinjava.chapter15;
public interface Factory<T>{
T create();
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class FacApple implements Factory<Apple>{
public Apple create(){
Random rand=new Random();
int i=rand.nextInt(3);
String c=new String();
switch(i){
case 0:
c="Red";
break;
case 1:
c="Green";
break;
case 2:
c="Yellow";
break;
}
return new Apple(c);
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class FacBanana {
public static class Fac implements Factory<Banana>{
public Banana create(){
Random rand=new Random();
int i=rand.nextInt(2);
String c=new String();
switch(i){
case 0:
c="Green";
break;
case 1:
c="Yellow";
break;
}
return new Banana(c);
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Plate<T>{
private List<T> list=new ArrayList<T>();
public <F extends Factory<T>> Plate(F f){
list.add(f.create());
}
public void add(Factory<T> f){list.add(f.create());}
public T get(int index){return (index<list.size())? list.get(index):null;}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise22{
public static void main(String[] args){
//测试苹果盘子
FacApple fa=new FacApple();
Plate<Apple> pa=new Plate<Apple>(fa);
pa.add(fa);
System.out.println(pa.get(0));
System.out.println(pa.get(1));
//测试香蕉盘子
FacBanana.Fac fb=new FacBanana.Fac();
Plate<Banana> pb=new Plate<Banana>(fb);
pb.add(fb);
System.out.println(pb.get(0));
System.out.println(pb.get(1));
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public interface FactoryI<T> {
List<T> create(int num);
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class IntegerFactory implements FactoryI<Integer> {
public List<Integer> create(int num) {
List<Integer> list=new ArrayList<Integer>();
for(int i=0;i<num;i++){
list.add(i);
}
return list;
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Foo2<T> {
private List<T> x;
public <F extends FactoryI<T>> Foo2(F factory, int num) {
x = factory.create(num);
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Widget {
public static class Factory implements FactoryI<Widget> {
public List<Widget> create(int num) {
List<Widget> list=new ArrayList<Widget>();
for(int i=0;i<num;i++){
list.add(new Widget());
}
return list;
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise23{
public static void main(String[] args) {
new Foo2<Integer>(new IntegerFactory(),10);
new Foo2<Widget>(new Widget.Factory(),10);
}
}
package com.ciaoshen.thinkinjava.chapter15;
public interface Factory<T>{
T create();
}
package com.ciaoshen.thinkinjava.chapter15;
public class Building {public Building(){System.out.println("I am Building!");}}
package com.ciaoshen.thinkinjava.chapter15;
public class House extends Building {public House(){System.out.println("I am House!");}}
package com.ciaoshen.thinkinjava.chapter15;
public class FacBuilding implements Factory<Building>{
public Building create(){return new Building();}
}
package com.ciaoshen.thinkinjava.chapter15;
public class FacBuilding implements Factory<Building>{
public Building create(){return new Building();}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise24 {
private Map<String,Factory<?>> typeMap=new HashMap<String,Factory<?>>();
public void addType(String key, Factory<?> value){
typeMap.put(key,value);
}
public Object createNew(String name){
Factory<?> f=typeMap.get(name);
try{
Object o=f.create();
return o;
}catch(Exception e){
System.out.println(e);
return null;
}
}
public static void main(String[] args) {
Exercise24 ctc=new Exercise24();
ctc.addType("Building",new FacBuilding());
ctc.addType("House",new FacHouse());
ctc.createNew("Hello"); //Exception: java.lang.NullPointerException
ctc.createNew("Building");
ctc.createNew("House");
}
}
package com.ciaoshen.thinkinjava.chapter15;
public interface Interface1{public void print1();}
package com.ciaoshen.thinkinjava.chapter15;
public interface Interface2{public void print2();}
package com.ciaoshen.thinkinjava.chapter15;
public class Implementation implements Interface1, Interface2{
public void print1(){System.out.println("Inherit from Interface1!");}
public void print2(){System.out.println("Inherit from Interface2!");}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise25{
public static <T extends Interface1> void foo1(T t){t.print1();}
public static <V extends Interface2> void foo2(V v){v.print2();}
public static void main(String[] args){
Exercise25.foo1(new Implementation());
Exercise25.foo2(new Implementation());
}
}
public class Exercise26{
public static void main(String[] args){
Number[] numArray=new Integer[10];
for(int i=0;i<10;i++){
numArray[i]=new Integer(i);
}
for(int i=0;i<10;i++){
System.out.println(numArray[i]);
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise27{
public static void main(String[] args){
//List<Number> numList1=new ArrayList<Integer>(); //Error
List<? extends Number> numList2=new ArrayList<Integer>();
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Generic1<T>{
private T item;
public Generic1(T t){item=t;}
public void set(T t){item=t;}
public String toString(){return String.valueOf(item);}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Generic2<T>{
private T item;
public Generic2(T t){item=t;}
public T get(){return item;}
}
public class Exercise28{
public static <T> void foo1(Generic1<? super T> g, T t){g.set(t);}
public static <V> V foo2(Generic2<? extends V> g){return g.get();}
public static void main(String[] args){
Generic1<Number> genNum=new Generic1<Number>(new Integer(0));
Generic2<Integer> genInt=new Generic2<Integer>(new Integer(222));
Exercise28.foo1(genNum, new Float(111.1f));
System.out.println(genNum);
Integer i=Exercise28.foo2(genInt);
System.out.println(i);
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Holder<T> {
private T obj;
public Holder(T t){obj=t;}
public void set(T obj) { this.obj = obj; }
public T get() { return obj; }
public String toString(){return obj.toString();}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise29{
public static void setList(List<?> l){
System.out.println(l.getClass().getSimpleName());
System.out.println(l.get(1));
}
public static void holderSet(Holder<? extends List<?>> h){
//h.set(new ArrayList<String>(Arrays.asList("Hello World".split(" ")))); //Error: mismatch; ArrayList<String> cannot be converted to CAP#1
}
public static List<?> holderGet(Holder<? extends List<?>> h){
return h.get();
}
public static void listSet(Holder<? extends List<?>> h){
List<?> list=h.get();
//list.add("TOTO"); //Error: mismatch; ArrayList<String> cannot be converted to CAP#1
}
public static Object listGet(Holder<? extends List<?>> h){
List<?> list=h.get();
return list.get(1);
}
public static void main(String[] args){
List<Integer> li=new ArrayList<Integer>();
li.addAll(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
Holder<List<Integer>> hli=new Holder<List<Integer>>(li);
System.out.println(hli);
Exercise29.setList(li);
//Exercise29.holderSet(hli); //Error: argument mismatch; ArrayList<String> cannot be converted to CAP#1
System.out.println(Exercise29.holderGet(hli));
//Exercise29.listSet(hli); //Error: argument mismatch; String cannot be converted to CAP#1
System.out.println(Exercise29.listGet(hli));
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Holder<T> {
private T obj;
public Holder(T t){obj=t;}
public void set(T obj) { this.obj = obj; }
public T get() { return obj; }
public String toString(){return obj.toString();}
}
package com.ciaoshen.thinkinjava.chapter15;
public class IntegerHolder extends Holder<Integer>{
public IntegerHolder(Integer i){super(i);}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise30{
public static void main(String[] args){
for(int i=0;i<10;i++){
IntegerHolder ih=new IntegerHolder(i);
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
public interface Payable {}
package com.ciaoshen.thinkinjava.chapter15;
public class Employee implements Payable {}
package com.ciaoshen.thinkinjava.chapter15;
class Hourly extends Employee {}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise31{
public static void main(String[] args){
Employee e=new Employee();
Hourly h=new Hourly();
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class FixedSizeStack<T> {
private int index = 0;
private Object[] storage;
public FixedSizeStack(int size) {
storage = new Object[size];
}
public void push(T item) { storage[index++] = item; }
@SuppressWarnings("unchecked")
public T pop() { return (T)storage[--index]; }
}
package com.ciaoshen.thinkinjava.chapter15;
public class Exercise32 {
public static final int SIZE = 10;
public static void main(String[] args) {
FixedSizeStack<String> strings = new FixedSizeStack<String>(SIZE);
for(String s : "A B C D E F G H I J".split(" ")){
strings.push(s);
}
//strings.push("end"); //Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
for(int i = 0; i < SIZE; i++) {
String s = strings.pop();
System.out.print(s + " ");
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class ArrayFixedSizeStack<T> {
private int index = 0;
private List<Object> storage;
public ArrayFixedSizeStack() {
storage = new ArrayList<Object>();
}
public void push(T item) { storage.add(item); index++; }
@SuppressWarnings("unchecked")
public T pop() { return (T)storage.get(--index); }
public boolean hasNext(){return index>0;}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise33 {
public static void main(String[] args) {
ArrayFixedSizeStack<String> strings = new ArrayFixedSizeStack<String>();
for(String s : "A B C D E F G H I J".split(" ")){
strings.push(s);
}
strings.push("end"); //Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
while(strings.hasNext()) {
String s = strings.pop();
System.out.print(s + " ");
}
}
}
自限定类对于需要互相比较的对象比较合适。相当于限定了圆形只能和圆形比较面积,长方形只能和长方形比较面积。
package com.ciaoshen.thinkinjava.chapter15;
import java.lang.Math.*;
public abstract class Shape<T extends Shape<T>>{
public boolean isLarger(T t){return this.area()>t.area();}
public boolean isSmaller(T t){return this.area()<t.area();}
public boolean equal(T t){return this.area()==t.area();}
public abstract double area();
}
package com.ciaoshen.thinkinjava.chapter15;
import java.lang.Math.*;
public class Circle extends Shape<Circle>{
private double radius;
public Circle(double r){radius=r;}
public double area(){
return Math.PI*radius*radius;
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.lang.Math.*;
public class Rectangle extends Shape<Rectangle>{
private double width;
private double height;
public Rectangle(double w, double h){width=w; height=h;}
public double area(){
return width*height;
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.lang.Math.*;
public class Exercise34 {
public static void main(String[] args) {
//自限定的意义在于:圆形只能和圆形比较面积
Circle c1=new Circle(11.1);
Circle c2=new Circle(15.5);
System.out.println(c1.isLarger(c2));
System.out.println(c1.isSmaller(c2));
System.out.println(c1.equal(c2));
//自限定的意义在于:长方形只能和长方形比较面积
Rectangle r1=new Rectangle(4.0,6.0);
Rectangle r2=new Rectangle(3.0,8.0);
System.out.println(r1.isLarger(r2));
System.out.println(r1.isSmaller(r2));
System.out.println(r1.equal(r2));
//不允许比较长方形和圆形的面积
System.out.println(r1.isLarger(c2));
System.out.println(r1.isSmaller(c2));
System.out.println(r1.equal(c2));
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Coffee{
private static long count;
private long id;
public Coffee(){id=count++;}
public long showId(){return id;}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Latte extends Coffee{
public String toString(){return "No."+String.valueOf(showId())+">>> I am Latte!";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Capuccino extends Coffee{
public String toString(){return "No."+String.valueOf(showId())+">>> I am Capuccino!";}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Esppresso extends Coffee{
public String toString(){return "No."+String.valueOf(showId())+">>> I am Esppresso!";}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise35{
@SuppressWarnings({"rawtypes","unchecked"})
static void oldStyleMethod(List probablyCapuccino) {
probablyCapuccino.add(new Latte());
}
@SuppressWarnings({"rawtypes","unchecked"})
public static void main(String[] args){
//unsafe list
List<Capuccino> capUnsafe=new ArrayList<Capuccino>();
Exercise35.oldStyleMethod(capUnsafe); //ClassCastException
//safe list
try{
List<Capuccino> capSafe=Collections.checkedList(new ArrayList<Capuccino>(), Capuccino.class);
Exercise35.oldStyleMethod(capSafe);
}catch(Exception e){
System.out.println(e);
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public interface Processor<T,E extends Exception, F extends Exception> {
public void process(List<T> resultCollector) throws E,F;
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class ProcessRunner<T,E extends Exception, F extends Exception> extends ArrayList<Processor<T,E,F>> {
private static final long serialVersionUID=0;
public List<T> processAll() throws E,F {
List<T> resultCollector = new ArrayList<T>();
for(Processor<T,E,F> processor : this){
processor.process(resultCollector);
}
return resultCollector;
}
}
package com.ciaoshen.thinkinjava.chapter15;
public class Failure1 extends Exception {private static final long serialVersionUID=0;}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Failure3 extends Exception {private static final long serialVersionUID=0;}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Processor1 implements Processor<String,Failure1,Failure3> {
private static int count = 3;
public void process(List<String> resultCollector) throws Failure1,Failure3 {
if(count>=5){
throw new Failure3();
}
if(count-- > 1){
resultCollector.add("Hep!");
}else{
resultCollector.add("Ho!");
}
if(count<-1){
throw new Failure1();
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Processor2 implements Processor<Integer,Failure2,Failure3> {
private static int count = 5;
public void process(List<Integer> resultCollector) throws Failure2,Failure3 {
if(count>=5){
throw new Failure3();
}
if(count-- == 0){
resultCollector.add(47);
} else {
resultCollector.add(11);
}
if(count<-1){
throw new Failure3();
}
}
}
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
public class Exercise36{
public static void main(String[] args){
ProcessRunner<String,Failure1,Failure3> runner = new ProcessRunner<String,Failure1,Failure3>();
for(int i = 0; i < 3; i++){
runner.add(new Processor1());
}
try {
System.out.println(runner.processAll());
} catch(Failure1 e1) {
System.out.println(e1);
} catch(Failure3 e3){
System.out.println(e3);
}
ProcessRunner<Integer,Failure2,Failure3> runner2 = new ProcessRunner<Integer,Failure2,Failure3>();
for(int i = 0; i < 5; i++){
runner2.add(new Processor2());
}
try {
System.out.println(runner2.processAll());
} catch(Failure2 e2) {
System.out.println(e2);
} catch(Failure3 e3){
System.out.println(e3);
}
}
}
/**
* 时间戳系统
*/
interface TimeStamped { long getStamp(); }
class TimeStampedImp implements TimeStamped {
private final long timeStamp;
public TimeStampedImp() {
timeStamp = new Date().getTime();
}
public long getStamp() { return timeStamp; }
}
/**
* 序列号系统
*/
interface SerialNumbered { long getSerialNumber(); }
class SerialNumberedImp implements SerialNumbered {
private static long counter = 1;
private final long serialNumber = counter++;
public long getSerialNumber() { return serialNumber; }
}
/**
* 版本系统(附加的第三个混型)
*/
interface VersionId { public double getVersionId();}
class VersionIdImp implements VersionId {
private double version=1.0;
public VersionIdImp(double v){version=v;}
public void progressVersion(){version+=0.1;}
public double getVersionId(){return version;}
}
/**
* 白板类系统
*/
interface Basic {
public void set(String val);
public String get();
}
class BasicImp implements Basic {
private String value;
public void set(String val) { value = val; }
public String get() { return value; }
}
/**
* 混型系统
*/
class Mixin extends BasicImp implements TimeStamped, SerialNumbered {
private TimeStamped timeStamp = new TimeStampedImp();
private SerialNumbered serialNumber = new SerialNumberedImp();
private VersionId id=new VersionIdImp(1.0);
public long getStamp() { return timeStamp.getStamp(); }
public long getSerialNumber() { return serialNumber.getSerialNumber(); }
public double getVersionId(){ return id.getVersionId();}
}
/**
* 测试
*/
public class Exercise37 {
public static void main(String[] args) {
Mixin mixin1 = new Mixin(), mixin2 = new Mixin();
mixin1.set("test string 1");
mixin2.set("test string 2");
System.out.println(mixin1.get() + " " + mixin1.getStamp() + " " + mixin1.getSerialNumber()+ " " + mixin1.getVersionId());
System.out.println(mixin2.get() + " " + mixin2.getStamp() + " " + mixin2.getSerialNumber()+ " " + mixin2.getVersionId());
}
}
class Coffee{
private int volumn;
public Coffee(int v){volumn=v;}
public void drink(int v){volumn= (v<=volumn)? volumn-v:0;}
public int checkRest(){return volumn;}
}
class Decorator extends Coffee{
Coffee c;
public Decorator(Coffee c, int ex){
super(c.checkRest()+ex);
this.c=c;
}
}
class MilkCoffee extends Decorator{
public MilkCoffee(Coffee c,int ex){
super(c,ex);
}
}
class FoamCoffee extends Decorator{
public FoamCoffee(Coffee c,int ex){
super(c,ex);
}
}
class CaramelCoffee extends Decorator{
public CaramelCoffee(Coffee c,int ex){
super(c,ex);
}
}
class ChocolateCoffee extends Decorator{
public ChocolateCoffee(Coffee c,int ex){
super(c,ex);
}
}
public class Exercise38 {
public static void main(String[] args) {
//制作玛奇朵
MilkCoffee latte=new MilkCoffee(new Coffee(10),10);
FoamCoffee cappuccino=new FoamCoffee(latte,5);
cappuccino.drink(7); //服务员偷喝一口
CaramelCoffee macchiato=new CaramelCoffee(cappuccino,3);
System.out.println(macchiato.checkRest());
macchiato.drink(10);
System.out.println(macchiato.checkRest());
}
}
/**
* tuple容器
*/
class TwoTuple<A,B> {
public final A first;
public final B second;
public TwoTuple(A a, B b) { first = a; second = b; }
public String toString() {
return "(" + first + ", " + second + ")";
}
public static <A,B> TwoTuple<A,B> tuple(A a, B b) {
return new TwoTuple<A,B>(a, b);
}
}
/**
* 时间戳系统
*/
interface TimeStamped { long getStamp(); }
class TimeStampedImp implements TimeStamped {
private final long timeStamp;
public TimeStampedImp() {
timeStamp = new Date().getTime();
}
public long getStamp() { return timeStamp; }
}
/**
* 序列号系统
*/
interface SerialNumbered { long getSerialNumber(); }
class SerialNumberedImp implements SerialNumbered {
private static long counter = 1;
private final long serialNumber = counter++;
public long getSerialNumber() { return serialNumber; }
}
/**
* 新加的Colored系统
*/
interface Colored {public boolean isColored();}
class ColoredImp implements Colored {
private boolean colored;
public ColoredImp(boolean c){colored=c;}
public void makeColor(){colored=true;}
public void removeColor(){colored=false;}
public boolean isColored(){return colored;}
}
/**
* 动态代理
*/
class MixinProxy implements InvocationHandler {
Map<String,Object> delegatesByMethod;
public MixinProxy(TwoTuple<Object,Class<?>>... pairs) {
delegatesByMethod = new HashMap<String,Object>();
for(TwoTuple<Object,Class<?>> pair : pairs) {
for(Method method : pair.second.getMethods()) {
String methodName = method.getName();
// The first interface in the map
// implements the method.
if (!delegatesByMethod.containsKey(methodName))
delegatesByMethod.put(methodName, pair.first);
}
}
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Object delegate = delegatesByMethod.get(methodName);
return method.invoke(delegate, args);
}
@SuppressWarnings("unchecked")
public static Object newInstance(TwoTuple... pairs) {
Class[] interfaces = new Class[pairs.length];
for(int i = 0; i < pairs.length; i++) {
interfaces[i] = (Class)pairs[i].second;
}
ClassLoader cl = pairs[0].first.getClass().getClassLoader();
return Proxy.newProxyInstance(cl, interfaces, new MixinProxy(pairs));
}
}
/**
* 测试
*/
public class Exercise39 {
public static void main(String[] args) {
Object mixin = MixinProxy.newInstance(TwoTuple.tuple(new BasicImp(), Basic.class),
TwoTuple.tuple(new TimeStampedImp(), TimeStamped.class),
TwoTuple.tuple(new SerialNumberedImp(),SerialNumbered.class),
TwoTuple.tuple(new ColoredImp(false),Colored.class));
Basic b = (Basic)mixin;
TimeStamped t = (TimeStamped)mixin;
SerialNumbered s = (SerialNumbered)mixin;
Colored c=(Colored)mixin;
b.set("Hello");
System.out.println(b.get());
System.out.println(t.getStamp());
System.out.println(s.getSerialNumber());
System.out.println(c.isColored());
}
}
/**
* Exercise 40
*/
package com.ciaoshen.thinkinjava.chapter15;
import java.util.*;
import java.lang.reflect.*;
/**
* LEV 1
*/
class Individual{
private String name;
public Individual(){this.name="NULL";}
public Individual(String name){this.name=name;}
public void speak(){System.out.println("...");}
}
/**
* LEV 2
*/
class Person extends Individual {
public Person(String name) { super(name); }
@Override
public void speak(){System.out.println("Hello World!");}
}
class Pet extends Individual {
public Pet(String name) { super(name); }
public Pet() { super(); }
@Override
public void speak(){System.out.println("!!!");}
}
/**
* LEV 3 - 狗,猫,鼠
*/
class Dog extends Pet {
public Dog(String name) { super(name); }
public Dog() { super(); }
@Override
public void speak(){System.out.println("WongWong!!!");}
}
class Cat extends Pet {
public Cat(String name) { super(name); }
public Cat() { super(); }
@Override
public void speak(){System.out.println("MiewMiew!!!");}
}
class Rodent extends Pet {
public Rodent(String name) { super(name); }
public Rodent() { super(); }
@Override
public void speak(){System.out.println("JiJiJi!!!");}
}
/**
* LEV 4 - 狗系
*/
class Mutt extends Dog {
public Mutt(String name) { super(name); }
public Mutt() { super(); }
}
class Pug extends Dog {
public Pug(String name) { super(name); }
public Pug() { super(); }
}
/**
* LEV 4 - 猫系
*/
class EgyptianMau extends Cat {
public EgyptianMau(String name) { super(name); }
public EgyptianMau() { super(); }
}
class Manx extends Cat {
public Manx(String name) { super(name); }
public Manx() { super(); }
}
/**
* LEV 4 - 鼠系
*/
class Rat extends Rodent {
public Rat(String name) { super(name); }
public Rat() { super(); }
}
class Mouse extends Rodent {
public Mouse(String name) { super(name); }
public Mouse() { super(); }
}
class Hamster extends Rodent {
public Hamster(String name) { super(name); }
public Hamster() { super(); }
}
/**
* Apply类
*/
class Apply {
public static <T, S extends Iterable<? extends T>> void apply(S seq, Method f, Object... args) {
try {
for(T t: seq)
f.invoke(t, args);
} catch(Exception e) {
// Failures are programmer errors
throw new RuntimeException(e);
}
}
}
/**
* 测试类
*/
public class Exercise40{
public static void main(String[] args){
List<Pet> lp=new ArrayList<Pet>();
lp.add(new Mutt("MuMu"));
lp.add(new Pug("PuPu"));
lp.add(new EgyptianMau("MauMau"));
lp.add(new Manx("ManMan"));
lp.add(new Rat("RaRa"));
lp.add(new Mouse("MouMou"));
lp.add(new Hamster("HaHa"));
try{
Apply.apply(lp,Pet.class.getMethod("speak"));
}catch(Exception e){
System.out.println(e);
}
}
}
//addable接口
interface Addable<T> { void add(T t); }
//面向Addable接口的fill方法
class FillPets {
//用反射填充容器
public static <T extends Pet> void fill(Addable<T> addable, Class<? extends T> classToken, int size) {
for(int i = 0; i < size; i++){
try {
addable.add(classToken.newInstance());
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
}
/** 《适配器》
* 原理是类库里的Collection和SimpleQueue动不了。
* 那就给他们都套一层代理。然后新的代理类实现Addable接口。
*/
//Collection是通过组合的方式套代理
class AddableCollectionAdapter<T> implements Addable<T> {
private Collection<T> c;
public AddableCollectionAdapter(Collection<T> c) {
this.c = c;
}
public void add(T item) { c.add(item); }
}
// 把加了add()方法的容器的引用,赋值给Addable接口。
class Adapter {
public static <T> Addable<T> collectionAdapter(Collection<T> c) {
return new AddableCollectionAdapter<T>(c);
}
}
//SimpleQueue
class SimpleQueue<T> implements Iterable<T> {
private LinkedList<T> storage = new LinkedList<T>();
public void add(T t) { storage.offer(t); }
public T get() { return storage.poll(); }
public Iterator<T> iterator() {
return storage.iterator();
}
}
//SimpleQueue的派生类实现Addable接口。
class AddableSimpleQueue<T> extends SimpleQueue<T> implements Addable<T> {
public void add(T item) { super.add(item); }
}
/**
* LEV 1
*/
class Individual{
private String name;
public Individual(){this.name="NULL";}
public Individual(String name){this.name=name;}
public void speak(){System.out.println("...");}
}
/**
* LEV 2
*/
class Person extends Individual {
public Person(String name) { super(name); }
@Override
public void speak(){System.out.println("Hello World!");}
}
class Pet extends Individual {
public Pet(String name) { super(name); }
public Pet() { super(); }
@Override
public void speak(){System.out.println("!!!");}
}
/**
* LEV 3 - 狗,猫,鼠
*/
class Dog extends Pet {
public Dog(String name) { super(name); }
public Dog() { super(); }
@Override
public void speak(){System.out.println("WongWong!!!");}
}
class Cat extends Pet {
public Cat(String name) { super(name); }
public Cat() { super(); }
@Override
public void speak(){System.out.println("MiewMiew!!!");}
}
class Rodent extends Pet {
public Rodent(String name) { super(name); }
public Rodent() { super(); }
@Override
public void speak(){System.out.println("JiJiJi!!!");}
}
/**
* LEV 4 - 狗系
*/
class Mutt extends Dog {
public Mutt(String name) { super(name); }
public Mutt() { super(); }
}
class Pug extends Dog {
public Pug(String name) { super(name); }
public Pug() { super(); }
}
/**
* LEV 4 - 猫系
*/
class EgyptianMau extends Cat {
public EgyptianMau(String name) { super(name); }
public EgyptianMau() { super(); }
}
class Manx extends Cat {
public Manx(String name) { super(name); }
public Manx() { super(); }
}
/**
* LEV 4 - 鼠系
*/
class Rat extends Rodent {
public Rat(String name) { super(name); }
public Rat() { super(); }
}
class Mouse extends Rodent {
public Mouse(String name) { super(name); }
public Mouse() { super(); }
}
class Hamster extends Rodent {
public Hamster(String name) { super(name); }
public Hamster() { super(); }
}
/**
* 测试类
*/
public class Exercise41{
public static void main(String[] args){
//Pet容器
List<Dog> dogs=new ArrayList<Dog>();
//给Pet容器套上实现了Addable接口的适配器,就能用面向Addable接口的fill()方法了。
Fill2.fill(new AddableCollectionAdapter<Dog>(dogs),Mutt.class, 3);
//用辅助方法获得Addable接口对象实例
Fill2.fill(Adapter.collectionAdapter(dogs), Pug.class, 2);
for(Dog d: dogs){
d.speak();
}
System.out.println("----------------------");
//SimpleQueue实现了Addable()接口与的派生类。也可以用fill()方法填充。
AddableSimpleQueue<Cat> catQueue = new AddableSimpleQueue<Cat>();
Fill2.fill(catQueue, EgyptianMau.class, 4);
Fill2.fill(catQueue, Manx.class, 1);
for(Cat c: catQueue){
c.speak();
}
}
}
/**
* 统一接口:黑箱子
*/
interface BlackBox<T>{
public void set(T t);
public T function();
}
/**
* 两个独立的类
*/
//魔数=31的简单散列值
class Hasher implements BlackBox<Long>{
private Long num=0l;
public void set(Long n){num=n;}
public Long function(){return 31*num;}
}
//返回5范围内的上下浮动值
class Floater implements BlackBox<Integer>{
private Integer num=0;
private Random rand=new Random();
public void set(Integer n){n=num;}
public Integer function(){return (rand.nextInt(2)==0)? num+rand.nextInt(5):num-rand.nextInt(5);}
}
/**
* Functional
*/
class NewFunctional{
public static <T> List<T> doSomething(Collection<T> c, BlackBox<T> bb){
List<T> result=new ArrayList<T>();
for(T t:c){
bb.set(t);
result.add(bb.function());
}
return result;
}
}
/**
* 测试
*/
public class Exercise42 {
public static void main(String[] args) {
List<Long> ll=new ArrayList<Long>();
ll.addAll(Arrays.asList(11111l,22222l,33333l,44444l,55555l));
List<Integer> li=new ArrayList<Integer>();
li.addAll(Arrays.asList(111,222,333,444,555));
List<Long> result1=NewFunctional.doSomething(ll,new Hasher());
System.out.println(result1);
List<Integer> result2=NewFunctional.doSomething(li,new Floater());
System.out.println(result2);
}
}