1.利用已有集合构建一个泛型Stack
我们知道Stack的基本特性是:只能对其顶部的元素进行操作(先进后出)
下面我们学习利用Jdk提供的泛型集合写一个泛型Stack,实现所有类型的push(弹入)和pop(弹出)
1 如果没有泛型
想象一下,如果没有泛型机制,我们该如何构建一个泛型栈?
相信大家和我一样,第一个想到的就是Object,所有对象的祖先,用它来接收所有类型的对象,然后在使用的时候进行强转。
大致实现如下:
import java.util.LinkedList;
public class ObjectStack {
//嵌套一个LinkedList来实现Stack
private LinkedList container = new LinkedList<>();
//弹入元素
public void push(Object t) {
container.addFirst(t);
}
//弹出元素
public Object pop() {
return container.removeFirst();
}
//判断栈容量是否为空
public boolean empty() {
return container.isEmpty();
}
}
这样做虽然可以但是,我们无法在前期知道我们编写的程序是否存在错误。
例如下面的使用:
public class ObjectStackTest {
public static void main(String[] args) {
ObjectStack stack = new ObjectStack();
stack.push("hello world");
int i = (int) stack.pop();
}
}
很明显,上面的程序是错误的,但是只有在运行时,我们才能发现错误!!
而泛型机制能让我们在编译时就能发现这样的错误并提醒我们。
2 利用泛型提前获知错误
下面我们使用泛型机制来重新编写这个Stack,
代码比较简单:
public class Stack<T> {
//嵌套一个Java已有的集合类LinkedList来实现Stack
private LinkedList<T> container = new LinkedList<>();
//弹入元素
public void push(T t) {
container.addFirst(t);
}
//弹出元素
public T pop() {
return container.removeFirst();
}
//判断栈容量是否为空
public boolean empty() {
return container.isEmpty();
}
}

很显然,聪明的IDEA试图提醒我们我们这里的编程错误,我们尝试用String类型接收int类型的数据,这是错误的行为。
在定义此类的引用元素时,我们用T这个泛型指代所有可能的类型,因此这个泛型类的实例可以用于存储所有引用类型的元素,并对其进行弹入和弹出操作,这体现了泛型的一个特性:面对类型编程。
上面的实现是通过简单的泛型类的组合构建的泛型类,实际上很多时候,这种方式的安全性要比纯底层构建泛型类高。
下面我们写一些例子来测试一下上面的泛型Stack是否能正确使用:
public class StackTest {
public static void main(String[] args) {
Stack<String> stack = new Stack<>();
System.out.println("向栈中增加字符串:");
System.out.println("Java大法");
System.out.println("细说Java");
System.out.println("Java从入门到精通(第2版)");
stack.push("Java大法");
stack.push("细说Java");
stack.push("Java从入门到精通(第2版)");
System.out.println("从栈中取出字符串:");
while (!stack.empty()) {
//删除栈中全部元素并进行输出
System.out.println(stack.pop());
}
}
}
运行结果:


浙公网安备 33010602011771号