public class Stack { PRivate int[] m_item; public int Pop(){...} public void Push(int item){...} public Stack(int i) { this.m_item = new int[i]; } } 上面代码运行的很好,但是,当我们需要一个栈来保存string类型时,该怎么办呢?很多人都会想到把上面的代码复制一份,把int改成string不就行了。当然,这样做本身是没有任何问题的,但一个优秀的程序是不会这样做的,因为他想到若以后再需要long、Node类型的栈该怎样做呢?还要再复制吗?优秀的程序员会想到用一个通用的数据类型object来实现这个栈:
public class Stack { private object[] m_item; public object Pop(){...} public void Push(object item){...} public Stack(int i) { this.m_item = new[i]; } } 这个栈写的不错,他非常灵活,可以接收任何数据类型,可以说是一劳永逸。但全面地讲,也不是没有缺陷的,主要表现在:
Node1 x = new Node1(); stack.Push(x); Node2 y = (Node2)stack.Pop(); 上面的代码在编译时是完全没问题的,但由于Push了一个Node1类型的数据,但在Pop时却要求转换为Node2类型,这将出现程序运行时的类型转换异常,但却逃离了编译器的检查。
public class Stack { private T[] m_item; public T Pop(){...} public void Push(T item){...} public Stack(int i) { this.m_item = new T[i]; } } 类的写法不变,只是引入了通用数据类型T就可以适用于任何数据类型,并且类型安全的。这个类的调用方法:
//实例化只能保存int类型的类 Stack a = new Stack(100); a.Push(10); a.Push("8888"); //这一行编译不通过,因为类a只接收int类型的数据 int x = a.Pop(); //实例化只能保存string类型的类 Stack b = new Stack(100); b.Push(10); //这一行编译不通过,因为类b只接收string类型的数据 b.Push("8888"); string y = b.Pop(); 这个类和object实现的类有截然不同的区别: