泛型的基本概念及优点
泛型:指参数化类型的能力
优点:(1)、能够在编译时而不是运行时检测出错误 (2)、提高软件的可靠性和可读性
用途:可以定义带泛型的类、接口和方法
- 定义带泛型的类和接口时,需要将泛型类型放在类名和接口名之后
示例
public class A<E>{
private Stack<E> s = new Stack<E>();
public E peek(){
return s.peek();
}
public void push(E e){
s.push(E);
}
}
2、定义一个带泛型的方法时,要将泛型类型放在方法返回类型之前
示例
public class A{
public static <E> void print(E[] e){
for(int i=0;i<e.length;i++)
System.out.println(e[i]);
}
}
//调用时
A.<Integer>print(integers); //integer = new Integer[10]
A.<String>print(strings); //strings = new String[10]
通配泛型
引入通配泛型的原因:
假设类A 有方法 public static void a(B < Object > b)
定义B的一个实例 B< Integer > b = new B< Integer >();
A.a(b) 调用会报错
原因:
尽管Integer 是Object 子类型,但B< Integer > 并不是B< Object > 的子类型
针对上面的情况,就需要引入通配泛型
通配泛型分类
- 非受限通配:< ? > 等价于 < ? extends Object >
- 受限通配: < ? extends T > T 或 T 的子类型
- 下限通配: < ? super T > T 或 T 的父类型
示例
public class Demo{
public static void main(String[] args){
Stack<Integer> intStack = new Stack<Integer>();
intStack.push(1);
intStack.push(2);
intStack.push(3);
print(intStack);
}
public static void print(Stack<? extends Number> stack){ //Number及其子类型
while(!stack.isEmpty())
System.out.println(stack.pop());
}
}
泛型使用过程中的注意事项
不能使用new E (); 即:不能使用泛型类型参数创建实例
原因:泛型是使用一种类型消除的方法来实现的,编译器使用泛型信息来编译代码,但是随后会清除它。
示例public class A<E>{ E e = new E(); //非法操作 }
不能使用new E[ ] 即:不能使用泛型类型参数创建数组
示例public class A<E>{ E[] ele = new E[10]; //非法操作 //可使用下面的方式进行规避 E[] ele = (E[]) new Object[10]; //合法 ArrayList<String> list = new ArrayList<String>[10]; //非法操作 //可使用下面的方式进行规避 ArrayList<String> list = (ArrayList<String>) new ArrayList[10] //合法 }
静态方法、数据域、初始化语句中为了类二引入泛型类型参数是非法的
示例public class A<E>{ ststic{ E e1; //非法 } public static void b(E e2){ //非法 } public static E e3; //非法 }
异常类不能是泛型的
示例public class MyException<T> extends Exception{ //非法 }