首先用Object实现一个简单的堆栈实例:
package Item29;
import java.util.Arrays;
import java.util.EmptyStackException;
/**
* @author: qujundong
* @date: 2020/11/29 上午9:36
* @description:
*/
public class StackObject {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public StackObject(){
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e){
ensureCapacity();
elements[size ++] = e;
}
public Object pop(){
if(size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null;
return result;
}
private boolean isEmpty(){
return size == 0;
}
private void ensureCapacity(){
if(elements.length == size){
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
@Override
public String toString() {
return "StackObject{" +
"elements=" + Arrays.toString(elements) +
", size=" + size +
'}';
}
public static void main(String[] args) {
StackObject stack = new StackObject();
stack.push(2);
stack.push(4);
stack.push("SS");
//客户端使用的时候很容易出现类型转换上的问题,并且编译找不出错误
//Integer s = (Integer)stack.pop()
System.out.println(stack.pop());
System.out.println(stack);
}
}
/*
SS
StackObject{elements=[2, 4, null, null, null, null, null, null, null, null, null, null, null, null, null, null], size=2}
*/
上述代码可以存入任意类型,这有一个坏处,如果客户端进行了错误的类型转换,在编译期无法报错,这是不使用泛型的坏处,下面尝试使用泛型,但是无法新建泛型数组,有两种解决办法,分别尝试。
1. 新建Object数组,声明泛型数组引用,通过强转将Object转成E
package Item29;
import java.util.Arrays;
import java.util.EmptyStackException;
/**
* @author: qujundong
* @date: 2020/11/29 上午9:48
* @description:
*/
public class StackGeneric<E> {
private E[] elements ;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
//因为使用类型转化会出现警告,但是确认没什么问题,所以取消未受检警告
@SuppressWarnings("unchecked")
public StackGeneric(){
//因为无法声明泛型数组,因此使用Object[]然后转化一下类型为E[]
elements = (E[])new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(E e){
ensureCapacity();
elements[size ++] = e;
}
public E pop(){
if(size == 0)
throw new EmptyStackException();
E result = elements[--size];
elements[size] = null;
return result;
}
private boolean isEmpty(){
return size == 0;
}
private void ensureCapacity(){
if(elements.length == size){
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
@Override
public String toString() {
return "StackObject{" +
"elements=" + Arrays.toString(elements) +
", size=" + size +
'}';
}
public static void main(String[] args) {
StackGeneric<Integer> stack = new StackGeneric<>();
stack.push(2);
stack.push(4);
System.out.println(stack.pop());
System.out.println(stack);
}
}
上述代码出现警告,因此用@SuppressWarnings(“unchecked”)解决
注: StackGeneric.java使用了未经检查或不安全的操作。
注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
2. 新建Object数组和引用
package Item29;
import java.util.Arrays;
import java.util.EmptyStackException;
/**
* @author: qujundong
* @date: 2020/11/29 上午9:48
* @description:
*/
public class StackGeneric2<E> {
private Object[] elements ;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public StackGeneric2(){
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(E e){
ensureCapacity();
elements[size ++] = e;
}
@SuppressWarnings("unchecked")
public E pop(){
if(size == 0)
throw new EmptyStackException();
//用泛型强转
E result = (E)elements[--size];
elements[size] = null;
return result;
}
private boolean isEmpty(){
return size == 0;
}
private void ensureCapacity(){
if(elements.length == size){
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
@Override
public String toString() {
return "StackObject{" +
"elements=" + Arrays.toString(elements) +
", size=" + size +
'}';
}
public static void main(String[] args) {
StackGeneric2<Integer> stack = new StackGeneric2<>();
stack.push(2);
stack.push(4);
System.out.println(stack.pop());
System.out.println(stack);
}
}
上述代码也会出现警告问题,不过出现在pop函数中,因此依然需要用@SuppressWarnings(“unchecked”)消除警告。
总结:使用泛型比在客户端进行类型转换要安全的多,并且也可以更早的发现错误,在编译期就解决。