泛型类
package com.mzm.chapter15;
/**
*
* 泛型类,持有泛化类型的对象,取出对象无需转型
*/
public class Holder3 {
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 h3 = new Holder3<>(new Automobile());
Automobile a = h3.get();
}
}
元组(tuple)是将一组对象直接打包存储的容器对象,这一容器对象容许读取其中的元素,但是不允许存放新的对象。元组也被称为数据传送对象或信使。
元组具有任意长度,其持有的对象可以是不同类型的。
package com.mzm.chapter15;
/**
* 二维元组
*
*/
public class TwoTuple {
public final A first;
public final B second;
public TwoTuple(A a, B b){
this.first = a;
this.second = b;
}
public String toString(){
return "(" + first + ", " + second + ")";
}
}
package com.mzm.chapter15;
/**
* 三维元组,使用继承机制实现长度更长的元组
*
*/
public class ThreeTuple<A, B, C> extends TwoTuple<A, B> {
public final C third;
public ThreeTuple(A a, B b, C c) {
super(a, b);
this.third = c;
}
public String toString() {
return "(" + first + ", " + second + ", " + third + ")";
}
}
更长的元组依次类推。
传统的下推堆栈
package com.mzm.chapter15;
/**
*
*/
public class LinkedStack {
private static class Node {
U item;
Node next;
Node() {
this.item = null;
this.next = null;
}
Node(U item, Node next) {
this.item = item;
this.next = next;
}
/**
* 末端哨兵,判断堆栈是否为空
* @return
*/
boolean end() {
return item == null && next == null;
}
}
private Node top = new Node<>();
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) {
LinkedStack lss = new LinkedStack<>();
for (String s : "Phasers on stun!".split(" ")) {
lss.push(s);
}
String s;
while((s = lss.pop()) != null) {
System.out.println(s);
}
}
}
package com.mzm.chapter15;
import java.util.ArrayList;
import java.util.Random;
/**
*
*/
public class RandomList {
private ArrayList storage = new ArrayList<>();
private Random rand = new Random(47);
public void add(T item) {
storage.add(item);
}
public T select() {
return storage.get(rand.nextInt(storage.size()));
}
public static void main(String[] args) {
RandomList rs = new RandomList<>();
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() + " ");
}
}
}
泛型接口的例子:
生成器(generator),是一种专门负责创建对象的类,是工厂方法设计模式的一种应用。不同的是,使用生成器创建对象时,不需要任何参数,而工厂方法一般需要参数。
package com.mzm.chapter15;
/**
* 生成器的通用接口
*/
public interface Generator {
T next();
}
package com.mzm.chapter15;
import java.util.Iterator;
import java.util.Random;
/**
* 使用生成器接口生成对象
*/
public class CoffeeGenerator implements Generator<Coffee>, Iterable<Coffee> {
private Class[] types = {
Latte.class,
Mocha.class,
Cappuccino.class,
Americano.class,
Breve.class,
};
private static Random rand = new Random(47);
public CoffeeGenerator() {
}
private int size = 0;
public CoffeeGenerator(int sz) {
this.size = sz;
}
@Override
public Coffee next() {
try {
return (Coffee) types[rand.nextInt(types.length)].newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
class CoffeeIterator implements Iterator<Coffee> {
int count = size;
@Override
public boolean hasNext() {
return count > 0;
}
@Override
public Coffee next() {
count--;
return CoffeeGenerator.this.next();
}
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(gen.next());
}
for(Coffee c : new CoffeeGenerator(5)) {
System.out.println(c);
}
}
}
是否拥有泛型方法与该类是不是泛型类无关。
定义泛型方法只需要将泛型参数列表置于返回值之前。
使用泛型类创建对象时必须指定类型参数,而在使用泛型方法时则不必指定类型参数,编译器会进行类型参数推断(type argument inference),找出具体的类型。
类型推断只对赋值操作有效,不能将一个泛型方法的返回结果作为参数,传递给另一个方法,因为编译器认为,泛型方法的返回值是被赋值给一个Object类型的变量(泛型方法的返回值类型实际上是Object类型?)。
显式类型说明
要想实现上述目的,可以使用显式类型说明。即在点操作符与方法名之间插入尖号,并指明类型。如果是在定义该方法的类内部,则在点操作符之前使用this关键字,如果是static方法,则在点操作符之前加类名。
package com.mzm.chapter15;
import com.mzm.chapter14.Person;
import com.mzm.chapter14.Pet;
import java.util.List;
import java.util.Map;
/**
*
*/
public class LimitsOfInference {
static void f(Map> petPeople) {
}
public static void main(String[] args) {
//f(New.map();
f(New.>map());
}
}
可变参数可与泛型方法并存
package com.mzm.chapter15;
/**
*
*/
public class BasicGenerator<T> implements Generator<T> {
private Class type;
public BasicGenerator(Class type) {
this.type = type;
}
@Override
public T next() {
try {
return type.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Generator create(Class type) {
return new BasicGenerator<>(type);
}
}
package com.mzm.chapter15;
import java.util.HashSet;
import java.util.Set;
/**
* 集合的各种运算
*
*/
public class Sets {
public static Set union(Set a, Set b) {
Set result = new HashSet<>(a);
result.addAll(b);
return result;
}
public static Set intersection(Set a, Set b) {
Set result = new HashSet<>(a);
result.retainAll(b);
return result;
}
public static Set difference(Set superset, Set subset) {
Set result = new HashSet<>(superset);
result.removeAll(subset);
return result;
}
public static Set complement(Set a, Set b) {
return difference(union(a, b), difference(a, b));
}
}
将泛型应用于匿名内部类
package com.mzm.chapter15;
import java.util.*;
/**
* Teller和Customer的默认构造器均为private,必须使用Generator创建对象
*
*/
public class BankTeller {
public static void serve(Teller t, Customer c) {
System.out.println(t + " servers " + c);
}
public static void main(String[] args) {
Random rand = new Random(47);
Queue line = new LinkedList<>();
Generators.fill(line, Customer.generator(), 15);
List tellers = new ArrayList<>();
Generators.fill(tellers, Teller.generator(), 4);
for(Customer c : line) {
serve(tellers.get(rand.nextInt(tellers.size())), c);
}
}
}
class Customer {
private static long counter = 1;
private final long id = counter++;
private Customer() {
}
public String toString() {
return getClass().getSimpleName() + " " + id;
}
public static Generator generator() {
return new Generator() {
@Override
public Customer next() {
return new Customer();
}
};
}
}
class Teller {
private static long counter = 1;
private final long id = counter++;
private Teller() {
}
public String toString() {
return getClass().getSimpleName() + " " + id;
}
public static Generator generator() {
return new Generator() {
@Override
public Teller next() {
return new Teller();
}
};
}
}
泛型可以简单而安全地创建复杂的模型。