很多原因促成了泛型的出现,而最引人注目的原因,是为了创建容器类。
620
package com.shan.thinkinginjava.generics;
// generics/HolderEx2.java
// TIJ4 Chapter Generics, Exercise 2, page 621
/* Create a holder class that holds three objects of the same type along
* with the methods to store and fetch those objects and a constructor to
* initialize all three.
*/
import typeinfo.pets.*;
/**
* 机器人
* @author sjtd
*
*/
class Robot {
private String name;
public Robot(String name) { this.name = name; }
public String toString() {
return name;
}
}
public class HolderEx2<T> {
private T x, y, z;
public HolderEx2(T x, T y, T z) {
this.x = x;
this.y = y;
this.z = z;
}
public void setX(T x) { this.x = x; }
public void setY(T y) { this.y = y; }
public void setZ(T z) { this.z = z; }
public T getX() { return x; }
public T getY() { return y; }
public T getZ() { return z; }
public String toString() {
return x + ", " + y + ", " + z;
}
public static void main(String[] args) {
Robot a = new Robot("bot1");
Robot b = new Robot("bot2");
Robot c = new Robot("bot3");
HolderEx2<Robot> hEx2 =
new HolderEx2<Robot>(a, b, c);
System.out.println("Holding: " + hEx2);
}
}
元组的概念
package com.shan.thinkinginjava.generics;
/**
*
* @author sjtd
*
* @param <A>
* @param <B>
* 对于一个函数的返回值,return仅仅允许返回单个对象
* 而元组,可以将一组元素打包存储于一个单一的对象
* 这个容器对象允许读取其中元素,但是不允许存放新的对象
*
*/
public class TwoTurple<A,B> {
//在这里A,B都是final的,这种方式很安全,
//如果程序员想使用新的元祖,就强制要求他们重新创建一个TwoTurple对象
public final A first;
public final B second;
public TwoTurple(A first, B second) {
this.first = first;
this.second = second;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "("+first +","+second+")";
}
public static void main(String[] args) {
//在这里编译期接受类型检查。compile failed;
//TwoTurple<String, Integer> tt = new TwoTurple<String, Integer>("a", "a");
TwoTurple<String, Integer> tt = new TwoTurple<String, Integer>("dan", 23);
System.out.println(tt.toString());
}
}
可以继承这个类,持有更多的对象,例如
package com.shan.thinkinginjava.generics;
import typeinfo.pets.Dog;
import typeinfo.pets.Gerbil;
import typeinfo.pets.Pet;
//generics/Holder3.java
//TIJ4 Chapter Generics, Exercise 1, page 621
//Use Holder3 with the typeinfo.pets library to show that a Holder3 that is
//specified to hold a base type can also hold a derived type.
public class Holder3<T> {
private T a;
public Holder3(T a) { this.a = a; }
public void set(T a) { this.a = a; }
public T get() { return a; }
public static void main(String[] args) {
Holder3<Pet> h3 =
new Holder3<Pet>(new Pet());
Pet a = h3.get(); // No cast needed
System.out.println(h3.get());
// can also hold a subclass of Pet:
h3.set(new Dog());
System.out.println(h3.get());
// can also hold a sububclass of Pet:
h3.set(new Gerbil());
System.out.println(h3.get());
}
}
624泛型化 innerclasses/Sequence.java类
package com.shan.thinkinginjava.generics;
// generics/GenericSequence.java
// TIJ4 Chapter Generics, Exercise 4, page 624
// 'Generify' innerclasses/Sequence.java.
import java.util.*;
/**
* 这个借口和java中的迭代器是一个原理的
* @author sjtd
*
*/
interface Selector {
boolean end();
Object current();
void next();
}
public class GenericSequence<E> {
private List<E> list = new ArrayList<E>();
//private int next = 0;
public GenericSequence(List<E> list) { this.list = list; }
public void add(E e) { list.add(e); }
/**
*
* 内部类实现了这个接口
*
*/
private class SequenceSelector implements Selector {
private int i = 0;
public boolean end() { return i == list.size(); }
public Object current() { return list.get(i); }
public void next() { if(i < list.size()) i++; }
}
public Selector selector() {
return new SequenceSelector();
}
public static void main(String[] args) {
List<String> ls = new ArrayList<String>();
GenericSequence<String> gs = new GenericSequence<String>(ls);
for(int i = 0; i < 10; i++)
gs.add(Integer.toString(i));
Selector selector = gs.selector();
while(!selector.end()) {
System.out.print(selector.current() + " ");
selector.next();
}
}
}