作者:云都小生
问题来源
我们先来看看其他博主提到泛型,都会贴出来的一个经典例子。
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];
}
}
这是一个模拟的栈类,但是这个类中,属性的数据类型都只能是int,或者说这个类只能处理int类型的数据。那如果我想这个栈能处理字符串类型的,怎么办?
public class Stack
{
private object[] m_item;
public object Pop(){...}
public void Push(object item){...}
public Stack(int i)
{
this.m_item = new object[i];
}
}
这样貌似解决了问题,无论是什么数据类型,都会继承自Object这个基类,这样我们在存放的时候,什么都可以往里面塞了。但是,你取出来的时候,就需要进行向下转型。
Node x = new Node();
statck.Push(x);
Node y = (Node)stack.Pop()
x一开始是个Node,但是当我们Push到Statck里面的时候,就变成了 object对象。取出来的时候,就需要转型成Node对象才能使用子类的方法。
这种方式确实可以,但是会出现异常,在你进行强制转型的时候,经常都会抛出异常,有没有什么方法可以完美解决这种问题?有的,那就是泛型。
泛型概述
泛型算是很多编程语言都支持的特性,它使程序增加了极大的灵活性,怎么回事呢?泛型可以对变量的数据类型进行限定,能够处理一种或多种特定类型对象,并且提高安全性。。
泛型还有一种好处,可以不明确指出具体的数据类型,会根据编译过程中具体的数据类型去动态的
后面我们来解释一下这其中的原理,先来看怎么用。
使用泛型
public class Stack<T>
{
private T[] m_item;
public T Pop(){...}
public void Push(T item){...}
public Stack(int i)
{
this.m_item = new T[i];
}
}
在定义该类的时候,我们就在后面加了个尖括号——<>,这个就表示泛型,我们写了一个T,这个T很像参数。T的意思是,我在创建该对象集合/数组的时候,指定的是什么数据类型,就只能传入什么数据类型,否则就会出错。
Stack<int> a = new Stack<int>(100);
a.Push(10);
a.Push("8888"); //这一行编译不通过,因为类a只接收int类型的数据
int x = a.Pop();
Stack<string> a = new Stack<string>(100);
a.Push("Data");
a.Push(8888); //这一行编译不通过,因为类a只接收string类型的数据
string x = a.Pop();
如此看来,泛型带来了三个好处,第一,不用怕在运行时产生异常,因为一旦指定了数据类型,数据不正确在编译时就会出错。第二,不需要什么强制转换,第三,你不需要重载很多次代码。
使用泛型加上继承
public class Node<T, V> where T : Class1,where V: Class2
可以用来限定,T只能是Class1或者继承自Class1,V只能是Class2或者继承自Class2。
public class Node<T, V> where T : class where V: struct
T只能是引用类型,V只能是数值类型。
泛型不仅仅可以用来限定类,还可以用来限定方法的参数。
public void 方法名(参数名<T>){}
2018/1/19 21:35:55 @Author:云都小生